Authors: Andrew Lewycky <andrew@transgaming.com>, Gavriel State <gav@transgaming.com>, Ove Kaaven <ovek@transgaming.com>
Major DirectDraw restructure/reimplementation, using an improved component
object model hierarchy. The implementation currently supports:
- DirectDraw over GDI/USER in a window (using DIBsections and
  asynchronous updates)
- XVidMode
- XF86DGA2
- All DirectDraw interfaces from versions 1 to 7 (at least in theory)
- Hooks for Direct3D interfaces

diff --git a/configure b/configure
index 993c9e9..d7fe6f9 100755
--- a/configure
+++ b/configure
@@ -3091,12 +3091,6 @@
 OPENGLFILES=""
 
 OPENGL32_DLL=""
-
-DGA_SRCS=""
-
-DGA2_SRCS=""
-
-MESA_SRCS=""
 if test "$have_x" = "yes"
 then
     XLIB="-lXext -lX11"
@@ -3107,17 +3101,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3111: checking for $ac_hdr" >&5
+echo "configure:3105: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3116 "configure"
+#line 3110 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3121: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3115: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3138,7 +3132,7 @@
 #define $ac_tr_hdr 1
 EOF
           echo $ac_n "checking for XpmCreatePixmapFromData in -lXpm""... $ac_c" 1>&6
-echo "configure:3142: checking for XpmCreatePixmapFromData in -lXpm" >&5
+echo "configure:3136: checking for XpmCreatePixmapFromData in -lXpm" >&5
 ac_lib_var=`echo Xpm'_'XpmCreatePixmapFromData | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3147,7 +3141,7 @@
 LIBS="-lXpm $X_LIBS -lXext -lX11 $X_EXTRA_LIBS
          $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3151 "configure"
+#line 3145 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3158,7 +3152,7 @@
 XpmCreatePixmapFromData()
 ; return 0; }
 EOF
-if { (eval echo configure:3162: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3156: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3203,17 +3197,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3207: checking for $ac_hdr" >&5
+echo "configure:3201: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3212 "configure"
+#line 3206 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3217: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3211: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3238,17 +3232,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3242: checking for $ac_hdr" >&5
+echo "configure:3236: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3247 "configure"
+#line 3241 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3252: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3246: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3269,7 +3263,7 @@
 #define $ac_tr_hdr 1
 EOF
                 echo $ac_n "checking for XkbQueryExtension in -lX11""... $ac_c" 1>&6
-echo "configure:3273: checking for XkbQueryExtension in -lX11" >&5
+echo "configure:3267: checking for XkbQueryExtension in -lX11" >&5
 ac_lib_var=`echo X11'_'XkbQueryExtension | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3277,7 +3271,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lX11 $X_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3281 "configure"
+#line 3275 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3288,7 +3282,7 @@
 XkbQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:3292: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3286: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3324,17 +3318,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3328: checking for $ac_hdr" >&5
+echo "configure:3322: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3333 "configure"
+#line 3327 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3338: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3332: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3355,7 +3349,7 @@
 #define $ac_tr_hdr 1
 EOF
                 echo $ac_n "checking for XShmQueryExtension in -lXext""... $ac_c" 1>&6
-echo "configure:3359: checking for XShmQueryExtension in -lXext" >&5
+echo "configure:3353: checking for XShmQueryExtension in -lXext" >&5
 ac_lib_var=`echo Xext'_'XShmQueryExtension | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3363,7 +3357,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lXext $X_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3367 "configure"
+#line 3361 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3374,7 +3368,7 @@
 XShmQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:3378: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3372: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3410,17 +3404,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3414: checking for $ac_hdr" >&5
+echo "configure:3408: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3419 "configure"
+#line 3413 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3424: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3418: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3441,7 +3435,7 @@
 #define $ac_tr_hdr 1
 EOF
                 echo $ac_n "checking for XShapeQueryExtension in -lXext""... $ac_c" 1>&6
-echo "configure:3445: checking for XShapeQueryExtension in -lXext" >&5
+echo "configure:3439: checking for XShapeQueryExtension in -lXext" >&5
 ac_lib_var=`echo Xext'_'XShapeQueryExtension | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3449,7 +3443,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lXext $X_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3453 "configure"
+#line 3447 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3460,7 +3454,7 @@
 XShapeQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:3464: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3496,17 +3490,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3500: checking for $ac_hdr" >&5
+echo "configure:3494: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3505 "configure"
+#line 3499 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3510: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3504: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3527,7 +3521,7 @@
 #define $ac_tr_hdr 1
 EOF
                               echo $ac_n "checking for XDGAQueryExtension in -lXxf86dga""... $ac_c" 1>&6
-echo "configure:3531: checking for XDGAQueryExtension in -lXxf86dga" >&5
+echo "configure:3525: checking for XDGAQueryExtension in -lXxf86dga" >&5
 ac_lib_var=`echo Xxf86dga'_'XDGAQueryExtension | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3536,7 +3530,7 @@
 LIBS="-lXxf86dga $X_LIBS -lXext -lX11 $X_EXTRA_LIBS
                $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3540 "configure"
+#line 3534 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3547,7 +3541,7 @@
 XDGAQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:3551: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3545: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3571,13 +3565,11 @@
 EOF
 
                   X_PRE_LIBS="$X_PRE_LIBS -lXxf86dga"
-                  DGA_SRCS='$(DGA_SRCS)'
-                  DGA2_SRCS='$(DGA2_SRCS)'
                
 else
   echo "$ac_t""no" 1>&6
                                      echo $ac_n "checking for XF86DGAQueryExtension in -lXxf86dga""... $ac_c" 1>&6
-echo "configure:3581: checking for XF86DGAQueryExtension in -lXxf86dga" >&5
+echo "configure:3573: checking for XF86DGAQueryExtension in -lXxf86dga" >&5
 ac_lib_var=`echo Xxf86dga'_'XF86DGAQueryExtension | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3586,7 +3578,7 @@
 LIBS="-lXxf86dga $X_LIBS -lXext -lX11 $X_EXTRA_LIBS
                    $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3590 "configure"
+#line 3582 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3597,7 +3589,7 @@
 XF86DGAQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:3601: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3593: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3617,7 +3609,6 @@
 EOF
 
                       X_PRE_LIBS="$X_PRE_LIBS -lXxf86dga"
-                      DGA_SRCS='$(DGA_SRCS)'
                     
 else
   echo "$ac_t""no" 1>&6
@@ -3639,17 +3630,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3643: checking for $ac_hdr" >&5
+echo "configure:3634: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3648 "configure"
+#line 3639 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3653: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3644: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3670,7 +3661,7 @@
 #define $ac_tr_hdr 1
 EOF
                   echo $ac_n "checking for XF86VidModeQueryExtension in -lXxf86vm""... $ac_c" 1>&6
-echo "configure:3674: checking for XF86VidModeQueryExtension in -lXxf86vm" >&5
+echo "configure:3665: checking for XF86VidModeQueryExtension in -lXxf86vm" >&5
 ac_lib_var=`echo Xxf86vm'_'XF86VidModeQueryExtension | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3679,7 +3670,7 @@
 LIBS="-lXxf86vm $X_LIBS -lXext -lX11 $X_EXTRA_LIBS
                  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3683 "configure"
+#line 3674 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3690,7 +3681,7 @@
 XF86VidModeQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:3694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3685: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3728,17 +3719,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3732: checking for $ac_hdr" >&5
+echo "configure:3723: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3737 "configure"
+#line 3728 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3742: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3733: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3759,7 +3750,7 @@
 #define $ac_tr_hdr 1
 EOF
                   echo $ac_n "checking for XvShmCreateImage in -lXv""... $ac_c" 1>&6
-echo "configure:3763: checking for XvShmCreateImage in -lXv" >&5
+echo "configure:3754: checking for XvShmCreateImage in -lXv" >&5
 ac_lib_var=`echo Xv'_'XvShmCreateImage | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3768,7 +3759,7 @@
 LIBS="-lXv $X_LIBS -lXext -lX11 $X_EXTRA_LIBS
                  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3772 "configure"
+#line 3763 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3779,7 +3770,7 @@
 XvShmCreateImage()
 ; return 0; }
 EOF
-if { (eval echo configure:3783: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3774: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3826,17 +3817,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3830: checking for $ac_hdr" >&5
+echo "configure:3821: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3835 "configure"
+#line 3826 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3840: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3831: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3865,19 +3856,19 @@
 	if test "$ac_cv_header_GL_gl_h" = "yes" -a "$ac_cv_header_GL_glx_h" = "yes"
 	then
 	    	    echo $ac_n "checking "for up-to-date OpenGL version"""... $ac_c" 1>&6
-echo "configure:3869: checking "for up-to-date OpenGL version"" >&5
+echo "configure:3860: checking "for up-to-date OpenGL version"" >&5
 if eval "test \"`echo '$''{'wine_cv_opengl_version_OK'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3874 "configure"
+#line 3865 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 int main() {
 GLenum test = GL_UNSIGNED_SHORT_5_6_5;
 ; return 0; }
 EOF
-if { (eval echo configure:3881: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3872: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_opengl_version_OK="yes"
 else
@@ -3894,21 +3885,21 @@
 echo "$ac_t""$wine_cv_opengl_version_OK" 1>&6
 
 	    	    echo $ac_n "checking "for thread-safe OpenGL version"""... $ac_c" 1>&6
-echo "configure:3898: checking "for thread-safe OpenGL version"" >&5
+echo "configure:3889: checking "for thread-safe OpenGL version"" >&5
 if eval "test \"`echo '$''{'wine_cv_opengl_version_threadsafe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_libs=$LIBS
 	       LIBS="$X_LIBS -lGL"
 	       cat > conftest.$ac_ext <<EOF
-#line 3905 "configure"
+#line 3896 "configure"
 #include "confdefs.h"
 
 int main() {
 pthread_getspecific();
 ; return 0; }
 EOF
-if { (eval echo configure:3912: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3903: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   wine_cv_opengl_version_threadsafe="yes"
 else
@@ -3927,7 +3918,7 @@
 	    if test "$wine_cv_opengl_version_OK" = "yes" -a \( "$wine_cv_opengl_version_threadsafe" = "no" -o $OPENGL = "yes" \)
             then
 				echo $ac_n "checking for glXCreateContext in -lGL""... $ac_c" 1>&6
-echo "configure:3931: checking for glXCreateContext in -lGL" >&5
+echo "configure:3922: checking for glXCreateContext in -lGL" >&5
 ac_lib_var=`echo GL'_'glXCreateContext | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3935,7 +3926,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lGL $X_LIBS -lXext -lX11 -lm $X_EXTRA_LIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3939 "configure"
+#line 3930 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3946,7 +3937,7 @@
 glXCreateContext()
 ; return 0; }
 EOF
-if { (eval echo configure:3950: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3941: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3962,7 +3953,6 @@
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   X_PRE_LIBS="$X_PRE_LIBS -lGL"
-			     MESA_SRCS='$(MESA_SRCS)'
 			     
 else
   echo "$ac_t""no" 1>&6
@@ -3979,7 +3969,7 @@
 
 
 			echo $ac_n "checking for glXGetProcAddressARB in -lGL""... $ac_c" 1>&6
-echo "configure:3983: checking for glXGetProcAddressARB in -lGL" >&5
+echo "configure:3973: checking for glXGetProcAddressARB in -lGL" >&5
 ac_lib_var=`echo GL'_'glXGetProcAddressARB | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3987,7 +3977,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lGL $X_LIBS -lXext -lX11 -lm $X_EXTRA_LIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3991 "configure"
+#line 3981 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3998,7 +3988,7 @@
 glXGetProcAddressARB()
 ; return 0; }
 EOF
-if { (eval echo configure:4002: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3992: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4025,12 +4015,12 @@
 			if test $ac_cv_lib_GL_glXGetProcAddressARB = "yes"
 			then
 			       echo $ac_n "checking "for OpenGL extension functions prototypes"""... $ac_c" 1>&6
-echo "configure:4029: checking "for OpenGL extension functions prototypes"" >&5
+echo "configure:4019: checking "for OpenGL extension functions prototypes"" >&5
 if eval "test \"`echo '$''{'wine_cv_extension_prototypes'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4034 "configure"
+#line 4024 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 				  		  #ifdef HAVE_GL_GLEXT_H
@@ -4041,7 +4031,7 @@
 PFNGLCOLORTABLEEXTPROC test_proc;
 ; return 0; }
 EOF
-if { (eval echo configure:4045: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4035: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_extension_prototypes="yes"
 else
@@ -4066,6 +4056,138 @@
 
 				OPENGL32_DLL=opengl32
 			fi
+
+                        for ac_hdr in GL/osmesa.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4065: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4070 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4075: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+                                  echo $ac_n "checking for OSMesaCreateContext in -lGL""... $ac_c" 1>&6
+echo "configure:4096: checking for OSMesaCreateContext in -lGL" >&5
+ac_lib_var=`echo GL'_'OSMesaCreateContext | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lGL $X_LIBS -lXext -lX11 $X_EXTRA_LIBS
+                                 $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4105 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char OSMesaCreateContext();
+
+int main() {
+OSMesaCreateContext()
+; return 0; }
+EOF
+if { (eval echo configure:4116: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<\EOF
+#define HAVE_OSMESA 1
+EOF
+
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for OSMesaCreateContext in -lOSMesa""... $ac_c" 1>&6
+echo "configure:4138: checking for OSMesaCreateContext in -lOSMesa" >&5
+ac_lib_var=`echo OSMesa'_'OSMesaCreateContext | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lOSMesa  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4146 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char OSMesaCreateContext();
+
+int main() {
+OSMesaCreateContext()
+; return 0; }
+EOF
+if { (eval echo configure:4157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+   cat >> confdefs.h <<\EOF
+#define HAVE_OSMESA 1
+EOF
+
+                                    X_PRE_LIBS="$X_PRE_LIBS -lOSMesa"
+                                  
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+                            
+else
+  echo "$ac_t""no" 1>&6
+echo "configure: warning: OSMesa not found!!" 1>&2
+                        
+fi
+done
+
 		fi
 	     fi
 	 fi
@@ -4086,17 +4208,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4090: checking for $ac_hdr" >&5
+echo "configure:4212: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4095 "configure"
+#line 4217 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4100: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4222: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4125,7 +4247,7 @@
     if test "$ac_cv_header_ncurses_h" = "yes"
     then 
         echo $ac_n "checking for waddch in -lncurses""... $ac_c" 1>&6
-echo "configure:4129: checking for waddch in -lncurses" >&5
+echo "configure:4251: checking for waddch in -lncurses" >&5
 ac_lib_var=`echo ncurses'_'waddch | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4133,7 +4255,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lncurses  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4137 "configure"
+#line 4259 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4144,7 +4266,7 @@
 waddch()
 ; return 0; }
 EOF
-if { (eval echo configure:4148: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4270: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4175,7 +4297,7 @@
     if test "$ac_cv_lib_ncurses_waddch" = "yes"
     then
         echo $ac_n "checking for resizeterm in -lncurses""... $ac_c" 1>&6
-echo "configure:4179: checking for resizeterm in -lncurses" >&5
+echo "configure:4301: checking for resizeterm in -lncurses" >&5
 ac_lib_var=`echo ncurses'_'resizeterm | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4183,7 +4305,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lncurses  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4187 "configure"
+#line 4309 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4194,7 +4316,7 @@
 resizeterm()
 ; return 0; }
 EOF
-if { (eval echo configure:4198: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4218,7 +4340,7 @@
 fi
 
         echo $ac_n "checking for getbkgd in -lncurses""... $ac_c" 1>&6
-echo "configure:4222: checking for getbkgd in -lncurses" >&5
+echo "configure:4344: checking for getbkgd in -lncurses" >&5
 ac_lib_var=`echo ncurses'_'getbkgd | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4226,7 +4348,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lncurses  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4230 "configure"
+#line 4352 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4237,7 +4359,7 @@
 getbkgd()
 ; return 0; }
 EOF
-if { (eval echo configure:4241: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4363: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4265,17 +4387,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4269: checking for $ac_hdr" >&5
+echo "configure:4391: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4274 "configure"
+#line 4396 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4279: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4401: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4304,7 +4426,7 @@
         if test "$ac_cv_header_curses_h" = "yes"
         then    
             echo $ac_n "checking for waddch in -lcurses""... $ac_c" 1>&6
-echo "configure:4308: checking for waddch in -lcurses" >&5
+echo "configure:4430: checking for waddch in -lcurses" >&5
 ac_lib_var=`echo curses'_'waddch | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4312,7 +4434,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lcurses  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4316 "configure"
+#line 4438 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4323,7 +4445,7 @@
 waddch()
 ; return 0; }
 EOF
-if { (eval echo configure:4327: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4449: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4353,7 +4475,7 @@
             if test "$ac_cv_lib_curses_waddch" = "yes"
             then
                 echo $ac_n "checking for resizeterm in -lcurses""... $ac_c" 1>&6
-echo "configure:4357: checking for resizeterm in -lcurses" >&5
+echo "configure:4479: checking for resizeterm in -lcurses" >&5
 ac_lib_var=`echo curses'_'resizeterm | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4361,7 +4483,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lcurses  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4365 "configure"
+#line 4487 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4372,7 +4494,7 @@
 resizeterm()
 ; return 0; }
 EOF
-if { (eval echo configure:4376: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4498: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4396,7 +4518,7 @@
 fi
 
                 echo $ac_n "checking for getbkgd in -lcurses""... $ac_c" 1>&6
-echo "configure:4400: checking for getbkgd in -lcurses" >&5
+echo "configure:4522: checking for getbkgd in -lcurses" >&5
 ac_lib_var=`echo curses'_'getbkgd | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4404,7 +4526,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lcurses  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4408 "configure"
+#line 4530 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4415,7 +4537,7 @@
 getbkgd()
 ; return 0; }
 EOF
-if { (eval echo configure:4419: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4444,12 +4566,12 @@
 fi
 
 echo $ac_n "checking "for GNU style IPX support"""... $ac_c" 1>&6
-echo "configure:4448: checking "for GNU style IPX support"" >&5
+echo "configure:4570: checking "for GNU style IPX support"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_ipx_gnu'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4453 "configure"
+#line 4575 "configure"
 #include "confdefs.h"
 #include <sys/socket.h>
     #include <netipx/ipx.h>
@@ -4457,7 +4579,7 @@
 ((struct sockaddr_ipx *)0)->sipx_family == AF_IPX
 ; return 0; }
 EOF
-if { (eval echo configure:4461: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4583: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_ipx_gnu="yes"
 else
@@ -4482,12 +4604,12 @@
 if test "$ac_cv_c_ipx_gnu" = "no"
 then
  echo $ac_n "checking "for linux style IPX support"""... $ac_c" 1>&6
-echo "configure:4486: checking "for linux style IPX support"" >&5
+echo "configure:4608: checking "for linux style IPX support"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_ipx_linux'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4491 "configure"
+#line 4613 "configure"
 #include "confdefs.h"
 #include <sys/socket.h>
      #include <asm/types.h>
@@ -4496,7 +4618,7 @@
 ((struct sockaddr_ipx *)0)->sipx_family == AF_IPX
 ; return 0; }
 EOF
-if { (eval echo configure:4500: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4622: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_ipx_linux="yes"
 else
@@ -4523,17 +4645,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4527: checking for $ac_hdr" >&5
+echo "configure:4649: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4532 "configure"
+#line 4654 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4537: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4659: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4561,12 +4683,12 @@
 
 
 echo $ac_n "checking "for Open Sound System"""... $ac_c" 1>&6
-echo "configure:4565: checking "for Open Sound System"" >&5
+echo "configure:4687: checking "for Open Sound System"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_opensoundsystem'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4570 "configure"
+#line 4692 "configure"
 #include "confdefs.h"
 
 	#if defined(HAVE_SYS_SOUNDCARD_H)
@@ -4587,7 +4709,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:4591: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4713: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_opensoundsystem="yes"
 else
@@ -4610,12 +4732,12 @@
 fi
 
 echo $ac_n "checking "for Open Sound System/MIDI interface"""... $ac_c" 1>&6
-echo "configure:4614: checking "for Open Sound System/MIDI interface"" >&5
+echo "configure:4736: checking "for Open Sound System/MIDI interface"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_opensoundsystem_midi'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4619 "configure"
+#line 4741 "configure"
 #include "confdefs.h"
 
 	#if defined(HAVE_SYS_SOUNDCARD_H)
@@ -4636,7 +4758,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:4640: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4762: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_opensoundsystem_midi="yes"
 else
@@ -4665,7 +4787,7 @@
 then
   CFLAGS="$CFLAGS -Wall"
   echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6
-echo "configure:4669: checking "for gcc strength-reduce bug"" >&5
+echo "configure:4791: checking "for gcc strength-reduce bug"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_gcc_strength_bug'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4673,7 +4795,7 @@
   ac_cv_c_gcc_strength_bug="yes"
 else
   cat > conftest.$ac_ext <<EOF
-#line 4677 "configure"
+#line 4799 "configure"
 #include "confdefs.h"
 
 int	L[4] = {0,1,2,3};
@@ -4688,7 +4810,7 @@
   exit( Array[1] != -2 || L[2] != 3);
 }
 EOF
-if { (eval echo configure:4692: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4814: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_gcc_strength_bug="no"
 else
@@ -4709,21 +4831,21 @@
   fi
 
     echo $ac_n "checking "for gcc -mpreferred-stack-boundary=2 support"""... $ac_c" 1>&6
-echo "configure:4713: checking "for gcc -mpreferred-stack-boundary=2 support"" >&5
+echo "configure:4835: checking "for gcc -mpreferred-stack-boundary=2 support"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_gcc_stack_boundary'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_cflags=$CFLAGS
   CFLAGS="$CFLAGS -mpreferred-stack-boundary=2"
   cat > conftest.$ac_ext <<EOF
-#line 4720 "configure"
+#line 4842 "configure"
 #include "confdefs.h"
 
 int main() {
 return 0
 ; return 0; }
 EOF
-if { (eval echo configure:4727: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4849: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_gcc_stack_boundary="yes"
 else
@@ -4746,7 +4868,7 @@
 
 
 echo $ac_n "checking "whether .type must sit inside a .def directive"""... $ac_c" 1>&6
-echo "configure:4750: checking "whether .type must sit inside a .def directive"" >&5
+echo "configure:4872: checking "whether .type must sit inside a .def directive"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_type_in_def'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4759,14 +4881,14 @@
 	.long 0
 EOF
 cat > conftest.$ac_ext <<EOF
-#line 4763 "configure"
+#line 4885 "configure"
 #include "confdefs.h"
 
 int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:4770: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4892: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_c_type_in_def="yes"
 else
@@ -4790,7 +4912,7 @@
  
 
 echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6
-echo "configure:4794: checking "whether external symbols need an underscore prefix"" >&5
+echo "configure:4916: checking "whether external symbols need an underscore prefix"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_extern_prefix'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4802,14 +4924,14 @@
 	.long 0
 EOF
 cat > conftest.$ac_ext <<EOF
-#line 4806 "configure"
+#line 4928 "configure"
 #include "confdefs.h"
 extern int ac_test;
 int main() {
 if (ac_test) return 1
 ; return 0; }
 EOF
-if { (eval echo configure:4813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4935: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_c_extern_prefix="yes"
 else
@@ -4833,7 +4955,7 @@
 
 
 echo $ac_n "checking "whether assembler accepts .string"""... $ac_c" 1>&6
-echo "configure:4837: checking "whether assembler accepts .string"" >&5
+echo "configure:4959: checking "whether assembler accepts .string"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_asm_string'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4843,14 +4965,14 @@
 	.string "test"
 EOF
 cat > conftest.$ac_ext <<EOF
-#line 4847 "configure"
+#line 4969 "configure"
 #include "confdefs.h"
 
 int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:4854: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4976: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_c_asm_string="yes"
 else
@@ -4878,21 +5000,21 @@
 if test "$LIBEXT" = "so"
 then
   echo $ac_n "checking "whether we can build a Linux dll"""... $ac_c" 1>&6
-echo "configure:4882: checking "whether we can build a Linux dll"" >&5
+echo "configure:5004: checking "whether we can build a Linux dll"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_dll_linux'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_cflags=$CFLAGS
   CFLAGS="$CFLAGS -fPIC -shared -Wl,-soname,conftest.so.1.0,-Bsymbolic"
   cat > conftest.$ac_ext <<EOF
-#line 4889 "configure"
+#line 5011 "configure"
 #include "confdefs.h"
 
 int main() {
 return 1
 ; return 0; }
 EOF
-if { (eval echo configure:4896: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5018: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_c_dll_linux="yes"
 else
@@ -4913,21 +5035,21 @@
     LDDLLFLAGS="-Wl,-Bsymbolic"
   else
     echo $ac_n "checking whether we can build a UnixWare (Solaris) dll""... $ac_c" 1>&6
-echo "configure:4917: checking whether we can build a UnixWare (Solaris) dll" >&5
+echo "configure:5039: checking whether we can build a UnixWare (Solaris) dll" >&5
 if eval "test \"`echo '$''{'ac_cv_c_dll_unixware'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_cflags=$CFLAGS
     CFLAGS="$CFLAGS -fPIC -Wl,-G,-h,conftest.so.1.0,-B,symbolic"
     cat > conftest.$ac_ext <<EOF
-#line 4924 "configure"
+#line 5046 "configure"
 #include "confdefs.h"
 
 int main() {
 return 1
 ; return 0; }
 EOF
-if { (eval echo configure:4931: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5053: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_c_dll_unixware="yes"
 else
@@ -4948,21 +5070,21 @@
       LDDLLFLAGS="-Wl,-B,symbolic"
     else
       echo $ac_n "checking "whether we can build a NetBSD dll"""... $ac_c" 1>&6
-echo "configure:4952: checking "whether we can build a NetBSD dll"" >&5
+echo "configure:5074: checking "whether we can build a NetBSD dll"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_dll_netbsd'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_cflags=$CFLAGS
       CFLAGS="$CFLAGS -fPIC -Wl,-Bshareable,-Bforcearchive"
       cat > conftest.$ac_ext <<EOF
-#line 4959 "configure"
+#line 5081 "configure"
 #include "confdefs.h"
 
 int main() {
 return 1
 ; return 0; }
 EOF
-if { (eval echo configure:4966: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5088: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_c_dll_netbsd="yes"
 else
@@ -5018,21 +5140,21 @@
 else
     DLL_LINK="-L\$(DLLDIR) \$(DLLS:%=-l%) \$(LIBWINE) \$(LIBUNICODE) \$(X_LIBS) \$(XLIB)"
     echo $ac_n "checking whether the linker supports --[no]-whole-archive (Linux)""... $ac_c" 1>&6
-echo "configure:5022: checking whether the linker supports --[no]-whole-archive (Linux)" >&5
+echo "configure:5144: checking whether the linker supports --[no]-whole-archive (Linux)" >&5
 if eval "test \"`echo '$''{'ac_cv_c_whole_archive'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_cflags=$CFLAGS
             CFLAGS="$CFLAGS -Wl,--whole-archive -Wl,--no-whole-archive"
             cat > conftest.$ac_ext <<EOF
-#line 5029 "configure"
+#line 5151 "configure"
 #include "confdefs.h"
 
 int main() {
 return 1
 ; return 0; }
 EOF
-if { (eval echo configure:5036: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5158: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_c_whole_archive="yes"
 else
@@ -5052,21 +5174,21 @@
         DLL_LINK="-Wl,--whole-archive $DLL_LINK -Wl,--no-whole-archive"
     else
         echo $ac_n "checking whether the linker supports -z {all,default}extract (Linux)""... $ac_c" 1>&6
-echo "configure:5056: checking whether the linker supports -z {all,default}extract (Linux)" >&5
+echo "configure:5178: checking whether the linker supports -z {all,default}extract (Linux)" >&5
 if eval "test \"`echo '$''{'ac_cv_c_allextract'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_cflags=$CFLAGS
 		CFLAGS="$CFLAGS -Wl,-z,allextract -Wl,-z,defaultextract"
 		cat > conftest.$ac_ext <<EOF
-#line 5063 "configure"
+#line 5185 "configure"
 #include "confdefs.h"
 
 int main() {
 return 1
 ; return 0; }
 EOF
-if { (eval echo configure:5070: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5192: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_c_allextract="yes"
 else
@@ -5098,7 +5220,7 @@
 
 wine_cv_libc_reentrant=no 
 echo $ac_n "checking "for reentrant libc: __errno_location"""... $ac_c" 1>&6
-echo "configure:5102: checking "for reentrant libc: __errno_location"" >&5
+echo "configure:5224: checking "for reentrant libc: __errno_location"" >&5
 if eval "test \"`echo '$''{'wine_cv_libc_r__errno_location'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -5106,14 +5228,14 @@
   wine_cv_libc_r__errno_location=yes 
 else
   cat > conftest.$ac_ext <<EOF
-#line 5110 "configure"
+#line 5232 "configure"
 #include "confdefs.h"
 int myerrno = 0;
 char buf[256];
 int *__errno_location(){return &myerrno;}
 main(){connect(0,buf,255); exit(!myerrno);}
 EOF
-if { (eval echo configure:5117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5239: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   wine_cv_libc_r__errno_location=yes
 else
@@ -5138,7 +5260,7 @@
     wine_cv_libc_reentrant=__errno_location 
 fi
 echo $ac_n "checking "for reentrant libc: __error"""... $ac_c" 1>&6
-echo "configure:5142: checking "for reentrant libc: __error"" >&5
+echo "configure:5264: checking "for reentrant libc: __error"" >&5
 if eval "test \"`echo '$''{'wine_cv_libc_r__error'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -5146,14 +5268,14 @@
   wine_cv_libc_r__error=yes 
 else
   cat > conftest.$ac_ext <<EOF
-#line 5150 "configure"
+#line 5272 "configure"
 #include "confdefs.h"
 int myerrno = 0;
 char buf[256];
 int *__error(){return &myerrno;}
 main(){connect(0,buf,255); exit(!myerrno);}
 EOF
-if { (eval echo configure:5157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   wine_cv_libc_r__error=yes
 else
@@ -5178,7 +5300,7 @@
     wine_cv_libc_reentrant=__error 
 fi
 echo $ac_n "checking "for reentrant libc: ___errno"""... $ac_c" 1>&6
-echo "configure:5182: checking "for reentrant libc: ___errno"" >&5
+echo "configure:5304: checking "for reentrant libc: ___errno"" >&5
 if eval "test \"`echo '$''{'wine_cv_libc_r___errno'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -5186,14 +5308,14 @@
   wine_cv_libc_r___errno=yes 
 else
   cat > conftest.$ac_ext <<EOF
-#line 5190 "configure"
+#line 5312 "configure"
 #include "confdefs.h"
 int myerrno = 0;
 char buf[256];
 int *___errno(){return &myerrno;}
 main(){connect(0,buf,255); exit(!myerrno);}
 EOF
-if { (eval echo configure:5197: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5319: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   wine_cv_libc_r___errno=yes
 else
@@ -5218,7 +5340,7 @@
     wine_cv_libc_reentrant=___errno 
 fi
 echo $ac_n "checking "for reentrant libc: __thr_errno"""... $ac_c" 1>&6
-echo "configure:5222: checking "for reentrant libc: __thr_errno"" >&5
+echo "configure:5344: checking "for reentrant libc: __thr_errno"" >&5
 if eval "test \"`echo '$''{'wine_cv_libc_r__thr_errno'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -5226,14 +5348,14 @@
   wine_cv_libc_r__thr_errno=yes 
 else
   cat > conftest.$ac_ext <<EOF
-#line 5230 "configure"
+#line 5352 "configure"
 #include "confdefs.h"
 int myerrno = 0;
 char buf[256];
 int *__thr_errno(){return &myerrno;}
 main(){connect(0,buf,255); exit(!myerrno);}
 EOF
-if { (eval echo configure:5237: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   wine_cv_libc_r__thr_errno=yes
 else
@@ -5269,7 +5391,7 @@
 if test "$have_x" = "yes" -a "$wine_cv_libc_reentrant" != "no"
 then
 echo $ac_n "checking "for reentrant X libraries"""... $ac_c" 1>&6
-echo "configure:5273: checking "for reentrant X libraries"" >&5
+echo "configure:5395: checking "for reentrant X libraries"" >&5
 if eval "test \"`echo '$''{'wine_cv_x_reentrant'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -5315,14 +5437,14 @@
 
 
 echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:5319: checking whether byte ordering is bigendian" >&5
+echo "configure:5441: checking whether byte ordering is bigendian" >&5
 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_bigendian=unknown
 # See if sys/param.h defines the BYTE_ORDER macro.
 cat > conftest.$ac_ext <<EOF
-#line 5326 "configure"
+#line 5448 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -5333,11 +5455,11 @@
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:5337: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5459: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   # It does; now see whether it defined to BIG_ENDIAN or not.
 cat > conftest.$ac_ext <<EOF
-#line 5341 "configure"
+#line 5463 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -5348,7 +5470,7 @@
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:5352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5474: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_bigendian=yes
 else
@@ -5368,7 +5490,7 @@
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 5372 "configure"
+#line 5494 "configure"
 #include "confdefs.h"
 main () {
   /* Are we little or big endian?  From Harbison&Steele.  */
@@ -5381,7 +5503,7 @@
   exit (u.c[sizeof (long) - 1] == 1);
 }
 EOF
-if { (eval echo configure:5385: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5507: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_bigendian=no
 else
@@ -5406,7 +5528,7 @@
 
 
 echo $ac_n "checking "whether bitfields are bigendian"""... $ac_c" 1>&6
-echo "configure:5410: checking "whether bitfields are bigendian"" >&5
+echo "configure:5532: checking "whether bitfields are bigendian"" >&5
 if eval "test \"`echo '$''{'wine_cv_bitfields_bigendian'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -5414,7 +5536,7 @@
   wine_cv_bitfields_bigendian=no 
 else
   cat > conftest.$ac_ext <<EOF
-#line 5418 "configure"
+#line 5540 "configure"
 #include "confdefs.h"
 
 union
@@ -5428,7 +5550,7 @@
 } u;
 main() { u.word = 0; u.bitfield.bit0 = 1; exit( u.word == 1 ); } 
 EOF
-if { (eval echo configure:5432: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   wine_cv_bitfields_bigendian=yes
 else
@@ -5452,7 +5574,7 @@
 fi
 
 echo $ac_n "checking "whether unaligned memory access is allowed"""... $ac_c" 1>&6
-echo "configure:5456: checking "whether unaligned memory access is allowed"" >&5
+echo "configure:5578: checking "whether unaligned memory access is allowed"" >&5
 if eval "test \"`echo '$''{'wine_cv_allow_unaligned_access'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -5460,7 +5582,7 @@
   wine_cv_allow_unaligned_access=no 
 else
   cat > conftest.$ac_ext <<EOF
-#line 5464 "configure"
+#line 5586 "configure"
 #include "confdefs.h"
 
 long volatile test[2];
@@ -5471,7 +5593,7 @@
     exit(0);
 } 
 EOF
-if { (eval echo configure:5475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5597: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   wine_cv_allow_unaligned_access=yes
 else
@@ -5499,19 +5621,19 @@
 # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
 # for constant arguments.  Useless!
 echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:5503: checking for working alloca.h" >&5
+echo "configure:5625: checking for working alloca.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5508 "configure"
+#line 5630 "configure"
 #include "confdefs.h"
 #include <alloca.h>
 int main() {
 void *p = alloca(2 * sizeof(int));
 ; return 0; }
 EOF
-if { (eval echo configure:5515: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_header_alloca_h=yes
 else
@@ -5532,12 +5654,12 @@
 fi
 
 echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:5536: checking for alloca" >&5
+echo "configure:5658: checking for alloca" >&5
 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5541 "configure"
+#line 5663 "configure"
 #include "confdefs.h"
 
 #ifdef __GNUC__
@@ -5565,7 +5687,7 @@
 char *p = (char *) alloca(1);
 ; return 0; }
 EOF
-if { (eval echo configure:5569: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_func_alloca_works=yes
 else
@@ -5597,12 +5719,12 @@
 
 
 echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:5601: checking whether alloca needs Cray hooks" >&5
+echo "configure:5723: checking whether alloca needs Cray hooks" >&5
 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5606 "configure"
+#line 5728 "configure"
 #include "confdefs.h"
 #if defined(CRAY) && ! defined(CRAY2)
 webecray
@@ -5627,12 +5749,12 @@
 if test $ac_cv_os_cray = yes; then
 for ac_func in _getb67 GETB67 getb67; do
   echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5631: checking for $ac_func" >&5
+echo "configure:5753: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5636 "configure"
+#line 5758 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5655,7 +5777,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:5659: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5682,7 +5804,7 @@
 fi
 
 echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:5686: checking stack direction for C alloca" >&5
+echo "configure:5808: checking stack direction for C alloca" >&5
 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -5690,7 +5812,7 @@
   ac_cv_c_stack_direction=0
 else
   cat > conftest.$ac_ext <<EOF
-#line 5694 "configure"
+#line 5816 "configure"
 #include "confdefs.h"
 find_stack_direction ()
 {
@@ -5709,7 +5831,7 @@
   exit (find_stack_direction() < 0);
 }
 EOF
-if { (eval echo configure:5713: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_stack_direction=1
 else
@@ -5766,12 +5888,12 @@
 
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5770: checking for $ac_func" >&5
+echo "configure:5892: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5775 "configure"
+#line 5897 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5794,7 +5916,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:5798: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5920: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5876,17 +5998,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:5880: checking for $ac_hdr" >&5
+echo "configure:6002: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5885 "configure"
+#line 6007 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:5890: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6012: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -5913,12 +6035,12 @@
 done
 
 echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
-echo "configure:5917: checking whether stat file-mode macros are broken" >&5
+echo "configure:6039: checking whether stat file-mode macros are broken" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5922 "configure"
+#line 6044 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -5971,12 +6093,12 @@
 
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:5975: checking for working const" >&5
+echo "configure:6097: checking for working const" >&5
 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5980 "configure"
+#line 6102 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -6025,7 +6147,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:6029: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6151: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -6046,21 +6168,21 @@
 fi
 
 echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:6050: checking for inline" >&5
+echo "configure:6172: checking for inline" >&5
 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_inline=no
 for ac_kw in inline __inline__ __inline; do
   cat > conftest.$ac_ext <<EOF
-#line 6057 "configure"
+#line 6179 "configure"
 #include "confdefs.h"
 
 int main() {
 } int $ac_kw foo() {
 ; return 0; }
 EOF
-if { (eval echo configure:6064: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6186: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_inline=$ac_kw; break
 else
@@ -6086,12 +6208,12 @@
 esac
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:6090: checking for ANSI C header files" >&5
+echo "configure:6212: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6095 "configure"
+#line 6217 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -6099,7 +6221,7 @@
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6103: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6225: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6116,7 +6238,7 @@
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 6120 "configure"
+#line 6242 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -6134,7 +6256,7 @@
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 6138 "configure"
+#line 6260 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -6155,7 +6277,7 @@
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 6159 "configure"
+#line 6281 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -6166,7 +6288,7 @@
 exit (0); }
 
 EOF
-if { (eval echo configure:6170: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:6292: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -6190,12 +6312,12 @@
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:6194: checking for size_t" >&5
+echo "configure:6316: checking for size_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6199 "configure"
+#line 6321 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -6223,7 +6345,7 @@
 fi
 
 echo $ac_n "checking size of long long""... $ac_c" 1>&6
-echo "configure:6227: checking size of long long" >&5
+echo "configure:6349: checking size of long long" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -6231,7 +6353,7 @@
   ac_cv_sizeof_long_long=0
 else
   cat > conftest.$ac_ext <<EOF
-#line 6235 "configure"
+#line 6357 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 main()
@@ -6242,7 +6364,7 @@
   exit(0);
 }
 EOF
-if { (eval echo configure:6246: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:6368: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_sizeof_long_long=`cat conftestval`
 else
@@ -6264,12 +6386,12 @@
 
    
 echo $ac_n "checking "whether we can use re-entrant gethostbyname_r Linux style"""... $ac_c" 1>&6
-echo "configure:6268: checking "whether we can use re-entrant gethostbyname_r Linux style"" >&5
+echo "configure:6390: checking "whether we can use re-entrant gethostbyname_r Linux style"" >&5
 if eval "test \"`echo '$''{'wine_cv_linux_gethostbyname_r_6'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6273 "configure"
+#line 6395 "configure"
 #include "confdefs.h"
 
 #include <netdb.h>
@@ -6290,7 +6412,7 @@
     
 ; return 0; }
 EOF
-if { (eval echo configure:6294: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6416: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_linux_gethostbyname_r_6=yes
 else
@@ -6316,12 +6438,12 @@
 if test "$ac_cv_header_linux_joystick_h" = "yes"
 then
    echo $ac_n "checking "whether linux/joystick.h uses the Linux 2.2+ API"""... $ac_c" 1>&6
-echo "configure:6320: checking "whether linux/joystick.h uses the Linux 2.2+ API"" >&5
+echo "configure:6442: checking "whether linux/joystick.h uses the Linux 2.2+ API"" >&5
 if eval "test \"`echo '$''{'wine_cv_linux_joystick_22_api'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6325 "configure"
+#line 6447 "configure"
 #include "confdefs.h"
 
 	#include <sys/ioctl.h>
@@ -6336,7 +6458,7 @@
 /*empty*/
 ; return 0; }
 EOF
-if { (eval echo configure:6340: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6462: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_linux_joystick_22_api=yes
 else
@@ -6363,12 +6485,12 @@
 if test "$ac_cv_header_sys_vfs_h" = "yes"
 then
     echo $ac_n "checking "whether sys/vfs.h defines statfs"""... $ac_c" 1>&6
-echo "configure:6367: checking "whether sys/vfs.h defines statfs"" >&5
+echo "configure:6489: checking "whether sys/vfs.h defines statfs"" >&5
 if eval "test \"`echo '$''{'wine_cv_sys_vfs_has_statfs'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6372 "configure"
+#line 6494 "configure"
 #include "confdefs.h"
 
 	#include <sys/types.h>
@@ -6385,7 +6507,7 @@
 	
 ; return 0; }
 EOF
-if { (eval echo configure:6389: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6511: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_sys_vfs_has_statfs=yes
 else
@@ -6412,12 +6534,12 @@
 if test "$ac_cv_header_sys_statfs_h" = "yes"
 then
     echo $ac_n "checking "whether sys/statfs.h defines statfs"""... $ac_c" 1>&6
-echo "configure:6416: checking "whether sys/statfs.h defines statfs"" >&5
+echo "configure:6538: checking "whether sys/statfs.h defines statfs"" >&5
 if eval "test \"`echo '$''{'wine_cv_sys_statfs_has_statfs'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6421 "configure"
+#line 6543 "configure"
 #include "confdefs.h"
 
 	#include <sys/types.h>
@@ -6432,7 +6554,7 @@
 	
 ; return 0; }
 EOF
-if { (eval echo configure:6436: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6558: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_sys_statfs_has_statfs=yes
 else
@@ -6459,12 +6581,12 @@
 if test "$ac_cv_header_sys_mount_h" = "yes"
 then
     echo $ac_n "checking "whether sys/mount.h defines statfs"""... $ac_c" 1>&6
-echo "configure:6463: checking "whether sys/mount.h defines statfs"" >&5
+echo "configure:6585: checking "whether sys/mount.h defines statfs"" >&5
 if eval "test \"`echo '$''{'wine_cv_sys_mount_has_statfs'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6468 "configure"
+#line 6590 "configure"
 #include "confdefs.h"
 
 	#include <sys/types.h>
@@ -6479,7 +6601,7 @@
 	
 ; return 0; }
 EOF
-if { (eval echo configure:6483: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6605: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_sys_mount_has_statfs=yes
 else
@@ -6505,7 +6627,7 @@
 
 
 echo $ac_n "checking "for statfs.f_bfree"""... $ac_c" 1>&6
-echo "configure:6509: checking "for statfs.f_bfree"" >&5
+echo "configure:6631: checking "for statfs.f_bfree"" >&5
 if eval "test \"`echo '$''{'wine_cv_statfs_bfree'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -6514,7 +6636,7 @@
         wine_cv_statfs_bfree=no
     else
     	cat > conftest.$ac_ext <<EOF
-#line 6518 "configure"
+#line 6640 "configure"
 #include "confdefs.h"
 
 	#include <sys/types.h>
@@ -6541,7 +6663,7 @@
 	
 ; return 0; }
 EOF
-if { (eval echo configure:6545: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6667: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_statfs_bfree=yes
 else
@@ -6565,7 +6687,7 @@
 fi
 
 echo $ac_n "checking "for statfs.f_bavail"""... $ac_c" 1>&6
-echo "configure:6569: checking "for statfs.f_bavail"" >&5
+echo "configure:6691: checking "for statfs.f_bavail"" >&5
 if eval "test \"`echo '$''{'wine_cv_statfs_bavail'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -6574,7 +6696,7 @@
         wine_cv_statfs_bavail=no
     else
     	cat > conftest.$ac_ext <<EOF
-#line 6578 "configure"
+#line 6700 "configure"
 #include "confdefs.h"
 
 	#include <sys/types.h>
@@ -6601,7 +6723,7 @@
 	
 ; return 0; }
 EOF
-if { (eval echo configure:6605: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6727: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   wine_cv_statfs_bavail=yes
 else
@@ -6626,12 +6748,12 @@
 
 
 echo $ac_n "checking "for msg_accrights in struct msghdr"""... $ac_c" 1>&6
-echo "configure:6630: checking "for msg_accrights in struct msghdr"" >&5
+echo "configure:6752: checking "for msg_accrights in struct msghdr"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_msg_accrights'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6635 "configure"
+#line 6757 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -6639,7 +6761,7 @@
 struct msghdr hdr; hdr.msg_accrights=0
 ; return 0; }
 EOF
-if { (eval echo configure:6643: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6765: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_msg_accrights="yes"
 else
@@ -6662,12 +6784,12 @@
 
 
 echo $ac_n "checking "for sun_len in struct sockaddr_un"""... $ac_c" 1>&6
-echo "configure:6666: checking "for sun_len in struct sockaddr_un"" >&5
+echo "configure:6788: checking "for sun_len in struct sockaddr_un"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_sun_len'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6671 "configure"
+#line 6793 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -6676,7 +6798,7 @@
 static struct sockaddr_un addr; addr.sun_len = 1
 ; return 0; }
 EOF
-if { (eval echo configure:6680: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6802: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_sun_len="yes"
 else
@@ -6699,12 +6821,12 @@
 
 
 echo $ac_n "checking "whether we need to define __i386__"""... $ac_c" 1>&6
-echo "configure:6703: checking "whether we need to define __i386__"" >&5
+echo "configure:6825: checking "whether we need to define __i386__"" >&5
 if eval "test \"`echo '$''{'ac_cv_cpp_def_i386'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6708 "configure"
+#line 6830 "configure"
 #include "confdefs.h"
 #if (defined(i386) || defined(__i386)) && !defined(__i386__)
 yes
@@ -7036,9 +7158,6 @@
 s%@XFILES@%$XFILES%g
 s%@OPENGLFILES@%$OPENGLFILES%g
 s%@OPENGL32_DLL@%$OPENGL32_DLL%g
-s%@DGA_SRCS@%$DGA_SRCS%g
-s%@DGA2_SRCS@%$DGA2_SRCS%g
-s%@MESA_SRCS@%$MESA_SRCS%g
 s%@DLL_LINK@%$DLL_LINK%g
 s%@DLLFLAGS@%$DLLFLAGS%g
 s%@LDSHARED@%$LDSHARED%g
@@ -7463,7 +7582,7 @@
 if test "$wine_cv_opengl_version_threadsafe" = "yes" -a $OPENGL = "yes"
 then
   echo
-  echo "*** Warning: you explicitely linked in a thread-safe OpenGL version. If you"
+  echo "*** Warning: you explicitly linked in a thread-safe OpenGL version. If you"
   echo "*** experience unusual crashes on DirectDraw games, try first to disable OpenGL"
   echo "*** support before reporting bugs."
 fi
diff --git a/configure.in b/configure.in
index 7fcd9e8..5108460 100644
--- a/configure.in
+++ b/configure.in
@@ -134,12 +134,6 @@
 OPENGLFILES=""
 AC_SUBST(OPENGL32_DLL)
 OPENGL32_DLL=""
-AC_SUBST(DGA_SRCS)
-DGA_SRCS=""
-AC_SUBST(DGA2_SRCS)
-DGA2_SRCS=""
-AC_SUBST(MESA_SRCS)
-MESA_SRCS=""
 if test "$have_x" = "yes"
 then
     XLIB="-lXext -lX11"
@@ -212,15 +206,12 @@
                   AC_DEFINE(HAVE_LIBXXF86DGA2)
                   AC_DEFINE(HAVE_LIBXXF86DGA)
                   X_PRE_LIBS="$X_PRE_LIBS -lXxf86dga"
-                  DGA_SRCS='$(DGA_SRCS)'
-                  DGA2_SRCS='$(DGA2_SRCS)'
                ],
                 [ dnl *** If not found, look for XF86DGAQueryExtension()
                   dnl *** instead (DGA 2.0 not found)...
                   AC_CHECK_LIB(Xxf86dga, XF86DGAQueryExtension,
                     [ AC_DEFINE(HAVE_LIBXXF86DGA)
                       X_PRE_LIBS="$X_PRE_LIBS -lXxf86dga"
-                      DGA_SRCS='$(DGA_SRCS)'
                     ],,
                     $X_LIBS -lXext -lX11 $X_EXTRA_LIBS
                   )
@@ -292,7 +283,6 @@
 		dnl Check for the presence of the library
 		AC_CHECK_LIB(GL,glXCreateContext,
 			     X_PRE_LIBS="$X_PRE_LIBS -lGL"
-			     MESA_SRCS='$(MESA_SRCS)'
 			     ,,
 			     $X_LIBS -lXext -lX11 -lm $X_EXTRA_LIBS)
 
@@ -324,6 +314,20 @@
 
 				OPENGL32_DLL=opengl32
 			fi
+
+                        AC_CHECK_HEADERS(GL/osmesa.h,
+                            [ dnl *** If GL/osmesa.h exists...
+                                AC_CHECK_LIB(GL, OSMesaCreateContext,
+                                  AC_DEFINE(HAVE_OSMESA),
+                                  AC_CHECK_LIB(OSMesa, OSMesaCreateContext,
+                                  [ AC_DEFINE(HAVE_OSMESA)
+                                    X_PRE_LIBS="$X_PRE_LIBS -lOSMesa"
+                                  ]),
+                                  $X_LIBS -lXext -lX11 $X_EXTRA_LIBS
+                                )
+                            ],
+                            AC_MSG_WARN([OSMesa not found!!])
+                        )
 		fi
 	     fi
 	 fi
@@ -1344,7 +1348,7 @@
 if test "$wine_cv_opengl_version_threadsafe" = "yes" -a $OPENGL = "yes"
 then
   echo
-  echo "*** Warning: you explicitely linked in a thread-safe OpenGL version. If you"
+  echo "*** Warning: you explicitly linked in a thread-safe OpenGL version. If you"
   echo "*** experience unusual crashes on DirectDraw games, try first to disable OpenGL"
   echo "*** support before reporting bugs."
 fi
diff --git a/dlls/ddraw/Makefile.in b/dlls/ddraw/Makefile.in
index fcdc594..a7457c6 100644
--- a/dlls/ddraw/Makefile.in
+++ b/dlls/ddraw/Makefile.in
@@ -4,51 +4,42 @@
 VPATH     = @srcdir@
 MODULE    = ddraw
 EXTRALIBS = $(LIBUUID)
-SOVERSION = 1.0
 IMPORTS   = user32 x11drv gdi32 kernel32
 
-MESA_SRCS = \
+OPENGLFILES = \
 	d3dcommon.c \
+	d3ddevice/main.c \
 	d3ddevice/mesa.c \
 	d3dexecutebuffer.c \
 	d3dlight.c \
 	d3dmaterial.c \
 	d3dtexture.c \
 	d3dviewport.c \
+	direct3d/main.c \
 	direct3d/mesa.c \
 	mesa.c
 
-DGA_SRCS = \
-	ddraw/dga.c \
-	dpalette/dga.c \
-	dsurface/dga.c \
-	dga.c
-
-DGA2_SRCS= \
-	dga2.c \
-	dsurface/dga2.c \
-	ddraw/dga2.c
-
-XFILES = \
-	@DGA_SRCS@ \
-	@MESA_SRCS@ \
-	@DGA2_SRCS@ \
-	ddraw/x11.c \
-	dpalette/x11.c \
-	dsurface/x11.c \
-	x11.c 
-
 C_SRCS = \
-	@XFILES@ \
+	@OPENGLFILES@ \
 	convert.c \
-	d3ddevice/main.c \
 	dclipper/main.c \
+	ddraw/dga2.c \
 	ddraw/main.c \
-	direct3d/main.c \
+	ddraw/thunks.c \
+	ddraw/user.c \
+	ddraw/xvidmode.c \
 	dpalette/main.c \
+	dsurface/dga2.c \
+	dsurface/dib.c \
+	dsurface/dibtexture.c \
+	dsurface/fakezbuffer.c \
 	dsurface/main.c \
+	dsurface/thunks.c \
+	dsurface/user.c \
+	dsurface/wndproc.c \
 	helper.c \
-	main.c
+	main.c \
+	struct_convert.c
 
 EXTRASUBDIRS = \
 	d3ddevice \
diff --git a/dlls/ddraw/convert.c b/dlls/ddraw/convert.c
index 386e1c5..bcb0060 100644
--- a/dlls/ddraw/convert.c
+++ b/dlls/ddraw/convert.c
@@ -224,12 +224,36 @@
     }
 }
 
-Convert ModeEmulations[7] = {
-  { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  24, 24, 0xFF0000, 0x0000FF00, 0x00FF }, { pixel_convert_32_to_24, NULL } },
-  { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_32_to_8,  palette_convert_24_to_8 } },
+/* *************************************
+      16 bpp to 32 bpp
+   ************************************* */
+static void pixel_convert_16_to_32(
+	void *src, void *dst, DWORD width, DWORD height, LONG pitch,
+	IDirectDrawPaletteImpl* palette
+) {
+    unsigned int *c_src = (unsigned int *) src;
+    unsigned short *c_dst = (unsigned short *) dst;
+    int y;
+
+    for (y = height; y--; ) {
+	unsigned int * srclineend = c_src+width;
+	while (c_src < srclineend ) {
+	    *c_dst++ = (((*c_src & 0xF80000) >> 8) |
+			((*c_src & 0x00FC00) >> 5) |
+			((*c_src & 0x0000F8) >> 3));
+	    c_src++;
+	}
+	c_src+=((pitch/4)-width);
+    }
+}
+
+Convert ModeEmulations[8] = {
+  { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  24, 24, 0xFF0000, 0x00FF00, 0x0000FF }, { pixel_convert_32_to_24, NULL } },
   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  16, 16, 0xF800, 0x07E0, 0x001F }, { pixel_convert_32_to_16, NULL } },
+  { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_32_to_8,  palette_convert_24_to_8 } },
   { { 24, 24,   0xFF0000,   0x00FF00,   0x0000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_24_to_8,  palette_convert_24_to_8 } },
   { { 16, 15,     0x7C00,     0x03E0,     0x001F }, {  16,16, 0xf800, 0x07e0, 0x001f }, { pixel_convert_15_to_16,  NULL } },
   { { 16, 16,     0xF800,     0x07E0,     0x001F }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8,  palette_convert_16_to_8 } },
   { { 16, 15,     0x7C00,     0x03E0,     0x001F }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8,  palette_convert_15_to_8 } },
+  { { 16, 16,     0xF800,     0x07E0,     0x001F }, {  32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, { pixel_convert_16_to_32, NULL } }
 };
diff --git a/dlls/ddraw/d3d_private.h b/dlls/ddraw/d3d_private.h
index 0b630f7..82cdb91 100644
--- a/dlls/ddraw/d3d_private.h
+++ b/dlls/ddraw/d3d_private.h
@@ -178,7 +178,7 @@
     /* IDirect3DTexture2 fields */
     void*			D3Ddevice; /* (void *) to use the same pointer
 					    * for both Direct3D and Direct3D2 */
-    IDirectDrawSurface4Impl*	surface;
+    IDirectDrawSurfaceImpl*	surface;
     LPVOID			private;
 };
 
@@ -535,8 +535,8 @@
 );
 
 /* All non-static functions 'exported' by various sub-objects */
-extern LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurface4Impl* surf);
-extern LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurface4Impl* surf);
+extern LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurfaceImpl* surf);
+extern LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurfaceImpl* surf);
 
 extern LPDIRECT3DLIGHT d3dlight_create_dx3(IDirect3DImpl* d3d1);
 extern LPDIRECT3DLIGHT d3dlight_create(IDirect3D2Impl* d3d2);
diff --git a/dlls/ddraw/d3ddevice/mesa.c b/dlls/ddraw/d3ddevice/mesa.c
index ad3dc29..63ea4e7 100644
--- a/dlls/ddraw/d3ddevice/mesa.c
+++ b/dlls/ddraw/d3ddevice/mesa.c
@@ -28,7 +28,6 @@
 #undef HAVE_BUGGY_MESAGL
 
 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)x->private)
-#define DDPRIVATE(x) x11_dd_private *ddpriv=((x11_dd_private*)(x)->d->private)
 
 #ifndef HAVE_GLEXT_PROTOTYPES
 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
@@ -48,8 +47,8 @@
  *				OpenGL static functions
  */
 static void set_context(IDirect3DDevice2Impl* This) {
+#if COMPILABLE
     D3DDPRIVATE(This);
-    DDPRIVATE(This->surface->s.ddraw);
 
 #ifdef USE_OSMESA
     OSMesaMakeCurrent(d3ddpriv->ctx, odev->buffer, GL_UNSIGNED_BYTE,
@@ -59,7 +58,8 @@
     if (glXMakeCurrent(display,ddpriv->drawable, odev->ctx) == False) {
 	ERR("Error in setting current context (context %p drawable %ld)!\n",
 	    odev->ctx, ddpriv->drawable);
-}
+    }
+#endif
 #endif
 }
 
@@ -123,6 +123,7 @@
 }
 
 static void fill_device_capabilities(IDirectDrawImpl* ddraw) {
+#if COMPILABLE
   x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
   const char *ext_string;
   Mesa_DeviceCapabilities *devcap;
@@ -140,6 +141,7 @@
     TRACE("Color table extension not found.\n");
   }
   LEAVE_GL();
+#endif
 }
 
 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
@@ -201,6 +203,7 @@
     else
       TRACE("Context created (%p)\n", odev->ctx);
     
+#if COMPILABLE
     /* Now override the surface's Flip method (if in double buffering) */
     ((x11_ds_private *) surface->private)->opengl_flip = TRUE;
     {
@@ -210,6 +213,7 @@
 	  if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
 	      ((x11_ds_private *) chain->surfaces[i]->private)->opengl_flip = TRUE;
     }
+#endif
 
 #endif
     odev->rs.src = GL_ONE;
@@ -295,21 +299,21 @@
   
   TRACE("Enumerating GL_RGBA unpacked (32)\n");
   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
-  pformat->u.dwRGBBitCount = 32;
-  pformat->u1.dwRBitMask =         0xFF000000;
-  pformat->u2.dwGBitMask =         0x00FF0000;
-  pformat->u3.dwBBitMask =        0x0000FF00;
-  pformat->u4.dwRGBAlphaBitMask = 0x000000FF;
+  pformat->u1.dwRGBBitCount = 32;
+  pformat->u2.dwRBitMask =         0xFF000000;
+  pformat->u3.dwGBitMask =         0x00FF0000;
+  pformat->u4.dwBBitMask =        0x0000FF00;
+  pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
   if (cb(&sdesc, context) == 0)
     return DD_OK;
 
   TRACE("Enumerating GL_RGB unpacked (24)\n");
   pformat->dwFlags = DDPF_RGB;
-  pformat->u.dwRGBBitCount = 24;
-  pformat->u1.dwRBitMask =  0x00FF0000;
-  pformat->u2.dwGBitMask =  0x0000FF00;
-  pformat->u3.dwBBitMask = 0x000000FF;
-  pformat->u4.dwRGBAlphaBitMask = 0x00000000;
+  pformat->u1.dwRGBBitCount = 24;
+  pformat->u2.dwRBitMask =  0x00FF0000;
+  pformat->u3.dwGBitMask =  0x0000FF00;
+  pformat->u4.dwBBitMask = 0x000000FF;
+  pformat->u5.dwRGBAlphaBitMask = 0x00000000;
   if (cb(&sdesc, context) == 0)
     return DD_OK;
 
@@ -318,62 +322,62 @@
      so that future version will work great. */
   TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
   pformat->dwFlags = DDPF_RGB;
-  pformat->u.dwRGBBitCount = 16;
-  pformat->u1.dwRBitMask =  0x0000F800;
-  pformat->u2.dwGBitMask =  0x000007E0;
-  pformat->u3.dwBBitMask = 0x0000001F;
-  pformat->u4.dwRGBAlphaBitMask = 0x00000000;
+  pformat->u1.dwRGBBitCount = 16;
+  pformat->u2.dwRBitMask =  0x0000F800;
+  pformat->u3.dwGBitMask =  0x000007E0;
+  pformat->u4.dwBBitMask = 0x0000001F;
+  pformat->u5.dwRGBAlphaBitMask = 0x00000000;
   if (cb(&sdesc, context) == 0)
     return DD_OK;
 
   TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
-  pformat->u.dwRGBBitCount = 16;
-  pformat->u1.dwRBitMask =         0x0000F800;
-  pformat->u2.dwGBitMask =         0x000007C0;
-  pformat->u3.dwBBitMask =        0x0000003E;
-  pformat->u4.dwRGBAlphaBitMask = 0x00000001;
+  pformat->u1.dwRGBBitCount = 16;
+  pformat->u2.dwRBitMask =         0x0000F800;
+  pformat->u3.dwGBitMask =         0x000007C0;
+  pformat->u4.dwBBitMask =        0x0000003E;
+  pformat->u5.dwRGBAlphaBitMask = 0x00000001;
   if (cb(&sdesc, context) == 0)
     return DD_OK;
 
   TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
-  pformat->u.dwRGBBitCount = 16;
-  pformat->u1.dwRBitMask =         0x0000F000;
-  pformat->u2.dwGBitMask =         0x00000F00;
-  pformat->u3.dwBBitMask =        0x000000F0;
-  pformat->u4.dwRGBAlphaBitMask = 0x0000000F;
+  pformat->u1.dwRGBBitCount = 16;
+  pformat->u2.dwRBitMask =         0x0000F000;
+  pformat->u3.dwGBitMask =         0x00000F00;
+  pformat->u4.dwBBitMask =        0x000000F0;
+  pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
   if (cb(&sdesc, context) == 0)
     return DD_OK;
 
   TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
   pformat->dwFlags = DDPF_RGB;
-  pformat->u.dwRGBBitCount = 8;
-  pformat->u1.dwRBitMask =         0x0000F800;
-  pformat->u2.dwGBitMask =         0x000007C0;
-  pformat->u3.dwBBitMask =        0x0000003E;
-  pformat->u4.dwRGBAlphaBitMask = 0x00000001;
+  pformat->u1.dwRGBBitCount = 8;
+  pformat->u2.dwRBitMask =         0x0000F800;
+  pformat->u3.dwGBitMask =         0x000007C0;
+  pformat->u4.dwBBitMask =        0x0000003E;
+  pformat->u5.dwRGBAlphaBitMask = 0x00000001;
   if (cb(&sdesc, context) == 0)
     return DD_OK;
 #endif
 
   TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
-  pformat->u.dwRGBBitCount = 16;
-  pformat->u1.dwRBitMask =         0x00007C00;
-  pformat->u2.dwGBitMask =         0x000003E0;
-  pformat->u3.dwBBitMask =         0x0000001F;
-  pformat->u4.dwRGBAlphaBitMask =  0x00008000;
+  pformat->u1.dwRGBBitCount = 16;
+  pformat->u2.dwRBitMask =         0x00007C00;
+  pformat->u3.dwGBitMask =         0x000003E0;
+  pformat->u4.dwBBitMask =         0x0000001F;
+  pformat->u5.dwRGBAlphaBitMask =  0x00008000;
   if (cb(&sdesc, context) == 0)
     return DD_OK;  
   
   TRACE("Enumerating Paletted (8)\n");
   pformat->dwFlags = DDPF_PALETTEINDEXED8;
-  pformat->u.dwRGBBitCount = 8;
-  pformat->u1.dwRBitMask =  0x00000000;
-  pformat->u2.dwGBitMask =  0x00000000;
-  pformat->u3.dwBBitMask = 0x00000000;
-  pformat->u4.dwRGBAlphaBitMask = 0x00000000;
+  pformat->u1.dwRGBBitCount = 8;
+  pformat->u2.dwRBitMask =  0x00000000;
+  pformat->u3.dwGBitMask =  0x00000000;
+  pformat->u4.dwBBitMask = 0x00000000;
+  pformat->u5.dwRGBAlphaBitMask = 0x00000000;
   if (cb(&sdesc, context) == 0)
     return DD_OK;
   
@@ -936,7 +940,7 @@
     glClearColor(0.0, 0.0, 0.0, 0.0);
     glColor3f(1.0, 1.0, 1.0);
     
-    fill_device_capabilities((IDirectDrawImpl *) surface->s.ddraw);
+    fill_device_capabilities((IDirectDrawImpl *) surface->ddraw_owner);
 
     return 1;
   }
diff --git a/dlls/ddraw/d3dtexture.c b/dlls/ddraw/d3dtexture.c
index 3013956..73b6f6d 100644
--- a/dlls/ddraw/d3dtexture.c
+++ b/dlls/ddraw/d3dtexture.c
@@ -100,7 +100,7 @@
 /*******************************************************************************
  *				Texture2 Creation functions
  */
-LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurface4Impl* surf)
+LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurfaceImpl* surf)
 {
   IDirect3DTexture2Impl* tex;
   
@@ -117,7 +117,7 @@
 /*******************************************************************************
  *				Texture Creation functions
  */
-LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurface4Impl* surf)
+LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurfaceImpl* surf)
 {
   IDirect3DTexture2Impl* tex;
   
@@ -144,10 +144,10 @@
   TRACE("(%p) : colorkey callback\n", texture);
 
   /* Get the texture description */
-  tex_d = &(texture->surface->s.surface_desc);
+  tex_d = (DDSURFACEDESC *)&(texture->surface->surface_desc);
   bpp = (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
 	 1 /* 8 bit of palette index */:
-	 tex_d->ddpfPixelFormat.u.dwRGBBitCount / 8 /* RGB bits for each colors */ );
+	 tex_d->ddpfPixelFormat.u1.dwRGBBitCount / 8 /* RGB bits for each colors */ );
   
   /* Now, save the current texture */
   ENTER_GL();
@@ -164,15 +164,15 @@
   if (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
     FIXME("Todo Paletted\n");
   } else if (tex_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
-    if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 8) {
+    if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
       FIXME("Todo 3_3_2_0\n");
-    } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 16) {
-      if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000000) {
+    } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
+      if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) {
 	/* Now transform the 5_6_5 into a 5_5_5_1 surface to support color keying */
 	unsigned short *dest = (unsigned short *) HeapAlloc(GetProcessHeap(),
 							    HEAP_ZERO_MEMORY,
 							    tex_d->dwWidth * tex_d->dwHeight * bpp);
-	unsigned short *src = (unsigned short *) tex_d->u1.lpSurface;
+	unsigned short *src = (unsigned short *) tex_d->lpSurface;
 	int x, y;
 
 	for (y = 0; y < tex_d->dwHeight; y++) {
@@ -199,16 +199,16 @@
 
 	/* Frees the temporary surface */
 	HeapFree(GetProcessHeap(),0,dest);
-      } else if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000001) {
+      } else if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) {
 	FIXME("Todo 5_5_5_1\n");
-      } else if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x0000000F) {
+      } else if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000000F) {
 	FIXME("Todo 4_4_4_4\n");
       } else {
 	ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
       }
-    } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 24) {
+    } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
       FIXME("Todo 8_8_8_0\n");
-    } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 32) {
+    } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
       FIXME("Todo 8_8_8_8\n");
     } else {
       ERR("Unhandled texture format (bad RGB count)\n");
@@ -366,15 +366,15 @@
   TRACE("Copied surface %p to surface %p\n", ilpD3DTexture2->surface, This->surface);
 
   /* Suppress the ALLOCONLOAD flag */
-  This->surface->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
+  This->surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
 
   /* Copy one surface on the other */
-  dst_d = &(This->surface->s.surface_desc);
-  src_d = &(ilpD3DTexture2->surface->s.surface_desc);
+  dst_d = (DDSURFACEDESC *)&(This->surface->surface_desc);
+  src_d = (DDSURFACEDESC *)&(ilpD3DTexture2->surface->surface_desc);
 
   /* Install the callbacks to the destination surface */
-  This->surface->s.texture = This;
-  This->surface->s.SetColorKey_cb = SetColorKey_cb;
+  This->surface->texture = This;
+  This->surface->SetColorKey_cb = SetColorKey_cb;
   
   if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
     /* Should also check for same pixel format, lPitch, ... */
@@ -385,12 +385,12 @@
     /* I should put a macro for the calculus of bpp */
     int bpp = (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
 	       1 /* 8 bit of palette index */:
-	       src_d->ddpfPixelFormat.u.dwRGBBitCount / 8 /* RGB bits for each colors */ );
+	       src_d->ddpfPixelFormat.u1.dwRGBBitCount / 8 /* RGB bits for each colors */ );
     GLuint current_texture;
 
     /* Copy the main memry texture into the surface that corresponds to the OpenGL
        texture object. */
-    memcpy(dst_d->u1.lpSurface, src_d->u1.lpSurface, src_d->dwWidth * src_d->dwHeight * bpp);
+    memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->dwWidth * src_d->dwHeight * bpp);
 
     ENTER_GL();
     
@@ -407,14 +407,16 @@
       /* ****************
 	 Paletted Texture
 	 **************** */
-      IDirectDrawPaletteImpl* pal = This->surface->s.palette;
+      IDirectDrawPaletteImpl* pal = This->surface->palette;
       BYTE table[256][4];
       int i;
 
+#if 0
       if (color_table_queried == FALSE) {
 	ptr_ColorTableEXT =
 	  ((Mesa_DeviceCapabilities *) ((x11_dd_private *) This->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT;
       }
+#endif
       
       if (pal == NULL) {
 	ERR("Palettized texture Loading with a NULL palette !\n");
@@ -427,9 +429,9 @@
 	table[i][0] = pal->palents[i].peRed;
 	table[i][1] = pal->palents[i].peGreen;
 	table[i][2] = pal->palents[i].peBlue;
-	if ((This->surface->s.surface_desc.dwFlags & DDSD_CKSRCBLT) &&
-	    (i >= This->surface->s.surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) &&
-	    (i <= This->surface->s.surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
+	if ((This->surface->surface_desc.dwFlags & DDSD_CKSRCBLT) &&
+	    (i >= This->surface->surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) &&
+	    (i <= This->surface->surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
 	  table[i][3] = 0x00;
 	else
 	table[i][3] = 0xFF;
@@ -454,11 +456,11 @@
 		     0,                   /* border */
 		     GL_COLOR_INDEX,      /* texture format */
 		     GL_UNSIGNED_BYTE,    /* texture type */
-		     src_d->u1.lpSurface); /* the texture */
+		     src_d->lpSurface); /* the texture */
       } else {
 	DWORD *surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
 	DWORD i;
-	BYTE *src = (BYTE *) src_d->u1.lpSurface, *dst = (BYTE *) surface;
+	BYTE *src = (BYTE *) src_d->lpSurface, *dst = (BYTE *) surface;
 	
 	for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
 	  BYTE color = *src++;
@@ -483,7 +485,7 @@
       /* ************
 	 RGB Textures
 	 ************ */
-      if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 8) {
+      if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
 	/* **********************
 	   GL_UNSIGNED_BYTE_3_3_2 
 	   ********************** */
@@ -494,9 +496,9 @@
 		     0,
 		     GL_RGB,
 		     GL_UNSIGNED_BYTE_3_3_2,
-		     src_d->u1.lpSurface);
-      } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 16) {
-	if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000000) {
+		     src_d->lpSurface);
+      } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
+	if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) {
 	    
 	  /* Texture snooping */
 	  SNOOP_5650();
@@ -508,8 +510,8 @@
 		       0,
 		       GL_RGB,
 		       GL_UNSIGNED_SHORT_5_6_5,
-		       src_d->u1.lpSurface);
-	} else if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000001) {
+		       src_d->lpSurface);
+	} else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) {
 	  /* Texture snooping */
 	  SNOOP_5551();
 	  
@@ -520,8 +522,8 @@
 		       0,
 		       GL_RGBA,
 		       GL_UNSIGNED_SHORT_5_5_5_1,
-		       src_d->u1.lpSurface);
-	} else if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x0000000F) {
+		       src_d->lpSurface);
+	} else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000000F) {
 	  glTexImage2D(GL_TEXTURE_2D,
 		       0,
 		       GL_RGBA,
@@ -529,12 +531,12 @@
 		       0,
 		       GL_RGBA,
 		       GL_UNSIGNED_SHORT_4_4_4_4,
-		       src_d->u1.lpSurface);
-	} else if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00008000) {
+		       src_d->lpSurface);
+	} else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00008000) {
 	  /* Converting the 1555 format in 5551 packed */
 	  WORD *surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
 	  DWORD i;
-	  WORD *src = (WORD *) src_d->u1.lpSurface, *dst = surface;
+	  WORD *src = (WORD *) src_d->lpSurface, *dst = surface;
 
 	  for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
 	    *dst++ = (((*src & 0x8000) >> 15) |
@@ -555,7 +557,7 @@
 	} else {
 	  ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
 	}
-      } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 24) {
+      } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
 	glTexImage2D(GL_TEXTURE_2D,
 		     0,
 		     GL_RGB,
@@ -563,8 +565,8 @@
 		     0,
 		     GL_RGB,
 		     GL_UNSIGNED_BYTE,
-		     src_d->u1.lpSurface);
-      } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 32) {
+		     src_d->lpSurface);
+      } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
 	glTexImage2D(GL_TEXTURE_2D,
 		     0,
 		     GL_RGBA,
@@ -572,7 +574,7 @@
 		     0,
 		     GL_RGBA,
 		     GL_UNSIGNED_BYTE,
-		     src_d->u1.lpSurface);
+		     src_d->lpSurface);
       } else {
 	ERR("Unhandled texture format (bad RGB count)\n");
       }
diff --git a/dlls/ddraw/dclipper/main.c b/dlls/ddraw/dclipper/main.c
index 5bb6f37..0290b04 100644
--- a/dlls/ddraw/dclipper/main.c
+++ b/dlls/ddraw/dclipper/main.c
@@ -1,43 +1,67 @@
 /*		DirectDrawClipper implementation
  *
  * Copyright 2000 Marcus Meissner
+ * Copyright 2000 TransGaming Technologies Inc.
  */
 
 #include "config.h"
 #include "winerror.h"
-
-#include <unistd.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
 #include "debugtools.h"
+
+#include <stdlib.h>
+
 #include "ddraw_private.h"
+#include "dclipper/main.h"
+#include "ddraw/main.h"
 
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
 /******************************************************************************
  *			DirectDrawCreateClipper (DDRAW.7)
  */
+
+static ICOM_VTABLE(IDirectDrawClipper) DDRAW_Clipper_VTable;
+
 HRESULT WINAPI DirectDrawCreateClipper(
     DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, LPUNKNOWN pUnkOuter
 ) {
-    IDirectDrawClipperImpl** ilplpDDClipper=(IDirectDrawClipperImpl**)lplpDDClipper;
-    TRACE("(%08lx,%p,%p)\n", dwFlags, ilplpDDClipper, pUnkOuter);
+    IDirectDrawClipperImpl* This;
+    TRACE("(%08lx,%p,%p)\n", dwFlags, lplpDDClipper, pUnkOuter);
 
-    *ilplpDDClipper = (IDirectDrawClipperImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipperImpl));
-    ICOM_VTBL(*ilplpDDClipper) = &ddclipvt;
-    (*ilplpDDClipper)->ref = 1;
-    (*ilplpDDClipper)->hWnd = 0; 
+    if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION;
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(IDirectDrawClipperImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    ICOM_INIT_INTERFACE(This, IDirectDrawClipper, DDRAW_Clipper_VTable);
+    This->ref = 1;
+    This->hWnd = 0; 
+    This->ddraw_owner = NULL;
+
+    *lplpDDClipper = ICOM_INTERFACE(This, IDirectDrawClipper);
     return DD_OK;
 }
 
+/* This is the classfactory implementation. */
+HRESULT DDRAW_CreateDirectDrawClipper(IUnknown* pUnkOuter, REFIID riid,
+				      LPVOID* ppObj)
+{
+    HRESULT hr;
+    LPDIRECTDRAWCLIPPER pClip;
+
+    hr = DirectDrawCreateClipper(0, &pClip, pUnkOuter);
+    if (FAILED(hr)) return hr;
+
+    hr = IDirectDrawClipper_QueryInterface(pClip, riid, ppObj);
+    IDirectDrawClipper_Release(pClip);
+    return hr;
+}
+
 /******************************************************************************
  *			IDirectDrawClipper
  */
-static HRESULT WINAPI IDirectDrawClipperImpl_SetHwnd(
+HRESULT WINAPI Main_DirectDrawClipper_SetHwnd(
     LPDIRECTDRAWCLIPPER iface, DWORD dwFlags, HWND hWnd
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
@@ -52,50 +76,77 @@
     return DD_OK;
 }
 
-static ULONG WINAPI IDirectDrawClipperImpl_Release(LPDIRECTDRAWCLIPPER iface) {
+static void Main_DirectDrawClipper_Destroy(IDirectDrawClipperImpl* This)
+{
+    if (This->ddraw_owner != NULL)
+	Main_DirectDraw_RemoveClipper(This->ddraw_owner, This);
+
+    HeapFree(GetProcessHeap(), 0 ,This);
+}
+
+void Main_DirectDrawClipper_ForceDestroy(IDirectDrawClipperImpl* This)
+{
+    WARN("deleting clipper %p with refcnt %lu\n", This, This->ref);
+    Main_DirectDrawClipper_Destroy(This);
+}
+
+ULONG WINAPI Main_DirectDrawClipper_Release(LPDIRECTDRAWCLIPPER iface) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
     TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
 
-    This->ref--;
-    if (This->ref)
-	return This->ref;
-    HeapFree(GetProcessHeap(),0,This);
-    return S_OK;
+    if (--This->ref == 0)
+    {
+	Main_DirectDrawClipper_Destroy(This);
+	return 0;
+    }
+    else return This->ref;
 }
 
-static HRESULT WINAPI IDirectDrawClipperImpl_GetClipList(
-    LPDIRECTDRAWCLIPPER iface,LPRECT rects,LPRGNDATA lprgn,LPDWORD hmm
+HRESULT WINAPI Main_DirectDrawClipper_GetClipList(
+    LPDIRECTDRAWCLIPPER iface,LPRECT prcClip,LPRGNDATA lprgn,LPDWORD pdwSize
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
-    FIXME("(%p,%p,%p,%p),stub!\n",This,rects,lprgn,hmm);
-    if (hmm) *hmm=0;
+    FIXME("(%p,%p,%p,%p),stub!\n",This,prcClip,lprgn,pdwSize);
+    abort();
+    if (pdwSize) *pdwSize=0;
     return DD_OK;
 }
 
-static HRESULT WINAPI IDirectDrawClipperImpl_SetClipList(
-    LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,DWORD hmm
+HRESULT WINAPI Main_DirectDrawClipper_SetClipList(
+    LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,DWORD pdwSize
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
-    FIXME("(%p,%p,%ld),stub!\n",This,lprgn,hmm);
+    FIXME("(%p,%p,%ld),stub!\n",This,lprgn,pdwSize);
+    abort();
     return DD_OK;
 }
 
-static HRESULT WINAPI IDirectDrawClipperImpl_QueryInterface(
+HRESULT WINAPI Main_DirectDrawClipper_QueryInterface(
     LPDIRECTDRAWCLIPPER iface, REFIID riid, LPVOID* ppvObj
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
-    FIXME("(%p)->(%p,%p),stub!\n",This,riid,ppvObj);
-    return OLE_E_ENUM_NOMORE;
+
+    if (IsEqualGUID(&IID_IUnknown, riid)
+	|| IsEqualGUID(&IID_IDirectDrawClipper, riid))
+    {
+	*ppvObj = ICOM_INTERFACE(This, IDirectDrawClipper);
+	++This->ref;
+	return S_OK;
+    }
+    else
+    {
+	return E_NOINTERFACE;
+    }
 }
 
-static ULONG WINAPI IDirectDrawClipperImpl_AddRef( LPDIRECTDRAWCLIPPER iface )
+ULONG WINAPI Main_DirectDrawClipper_AddRef( LPDIRECTDRAWCLIPPER iface )
 {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
     TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
-    return ++(This->ref);
+    return ++This->ref;
 }
 
-static HRESULT WINAPI IDirectDrawClipperImpl_GetHWnd(
+HRESULT WINAPI Main_DirectDrawClipper_GetHWnd(
     LPDIRECTDRAWCLIPPER iface, HWND* hWndPtr
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
@@ -106,32 +157,44 @@
     return DD_OK;
 }
 
-static HRESULT WINAPI IDirectDrawClipperImpl_Initialize(
+HRESULT WINAPI Main_DirectDrawClipper_Initialize(
      LPDIRECTDRAWCLIPPER iface, LPDIRECTDRAW lpDD, DWORD dwFlags
 ) {
+    IDirectDrawImpl* pOwner;
     ICOM_THIS(IDirectDrawClipperImpl,iface);
     FIXME("(%p)->(%p,0x%08lx),stub!\n",This,lpDD,dwFlags);
+
+    if (This->ddraw_owner != NULL) return DDERR_ALREADYINITIALIZED;
+
+    pOwner = ICOM_OBJECT(IDirectDrawImpl, IDirectDraw, lpDD);
+    This->ddraw_owner = pOwner;
+    Main_DirectDraw_AddClipper(pOwner, This);
+
     return DD_OK;
 }
 
-static HRESULT WINAPI IDirectDrawClipperImpl_IsClipListChanged(
+HRESULT WINAPI Main_DirectDrawClipper_IsClipListChanged(
     LPDIRECTDRAWCLIPPER iface, BOOL* lpbChanged
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
     FIXME("(%p)->(%p),stub!\n",This,lpbChanged);
+
+    /* XXX What is safest? */
+    *lpbChanged = FALSE;
+
     return DD_OK;
 }
 
-ICOM_VTABLE(IDirectDrawClipper) ddclipvt = 
+static ICOM_VTABLE(IDirectDrawClipper) DDRAW_Clipper_VTable =
 {
     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    IDirectDrawClipperImpl_QueryInterface,
-    IDirectDrawClipperImpl_AddRef,
-    IDirectDrawClipperImpl_Release,
-    IDirectDrawClipperImpl_GetClipList,
-    IDirectDrawClipperImpl_GetHWnd,
-    IDirectDrawClipperImpl_Initialize,
-    IDirectDrawClipperImpl_IsClipListChanged,
-    IDirectDrawClipperImpl_SetClipList,
-    IDirectDrawClipperImpl_SetHwnd
+    Main_DirectDrawClipper_QueryInterface,
+    Main_DirectDrawClipper_AddRef,
+    Main_DirectDrawClipper_Release,
+    Main_DirectDrawClipper_GetClipList,
+    Main_DirectDrawClipper_GetHWnd,
+    Main_DirectDrawClipper_Initialize,
+    Main_DirectDrawClipper_IsClipListChanged,
+    Main_DirectDrawClipper_SetClipList,
+    Main_DirectDrawClipper_SetHwnd
 };
diff --git a/dlls/ddraw/dclipper/main.h b/dlls/ddraw/dclipper/main.h
new file mode 100644
index 0000000..74063dd
--- /dev/null
+++ b/dlls/ddraw/dclipper/main.h
@@ -0,0 +1,35 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef WINE_DDRAW_DCLIPPER_MAIN_H_INCLUDED
+#define WINE_DDRAW_DCLIPPER_MAIN_H_INCLUDED
+
+HRESULT WINAPI DirectDrawCreateClipper(DWORD dwFlags,
+				       LPDIRECTDRAWCLIPPER* ppClipper,
+				       LPUNKNOWN pUnkOuter);
+HRESULT DDRAW_CreateClipper(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppObj);
+void Main_DirectDrawClipper_ForceDestroy(IDirectDrawClipperImpl* This);
+
+HRESULT WINAPI
+Main_DirectDrawClipper_SetHwnd(LPDIRECTDRAWCLIPPER iface, DWORD dwFlags,
+			       HWND hWnd);
+ULONG WINAPI Main_DirectDrawClipper_Release(LPDIRECTDRAWCLIPPER iface);
+HRESULT WINAPI
+Main_DirectDrawClipper_GetClipList(LPDIRECTDRAWCLIPPER iface,LPRECT prcClip,
+				   LPRGNDATA lprgn,LPDWORD pdwSize);
+HRESULT WINAPI
+Main_DirectDrawClipper_SetClipList(LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,
+				   DWORD pdwSize);
+HRESULT WINAPI
+Main_DirectDrawClipper_QueryInterface(LPDIRECTDRAWCLIPPER iface, REFIID riid,
+				      LPVOID* ppvObj);
+ULONG WINAPI Main_DirectDrawClipper_AddRef( LPDIRECTDRAWCLIPPER iface );
+HRESULT WINAPI
+Main_DirectDrawClipper_GetHWnd(LPDIRECTDRAWCLIPPER iface, HWND* hWndPtr);
+HRESULT WINAPI
+Main_DirectDrawClipper_Initialize(LPDIRECTDRAWCLIPPER iface, LPDIRECTDRAW lpDD,
+				  DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawClipper_IsClipListChanged(LPDIRECTDRAWCLIPPER iface,
+					 BOOL* lpbChanged);
+
+#endif
diff --git a/dlls/ddraw/ddcomimpl.h b/dlls/ddraw/ddcomimpl.h
new file mode 100644
index 0000000..da4afd8
--- /dev/null
+++ b/dlls/ddraw/ddcomimpl.h
@@ -0,0 +1,39 @@
+/* A few helpful macros for implementing COM objects.
+ *
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include <stddef.h>
+
+/* Generates the name for a vtable pointer for a given interface. */
+/* The canonical name for a single interface is "lpVtbl". */
+#define ICOM_VFIELD_MULTI_NAME2(iface) ITF_##iface
+#define ICOM_VFIELD_MULTI_NAME(iface) ICOM_VFIELD_MULTI_NAME2(iface)
+
+/* Declares a vtable pointer field in an implementation. */
+#define ICOM_VFIELD_MULTI(iface) \
+	iface ICOM_VFIELD_MULTI_NAME(iface)
+
+/* Returns the offset of a vtable pointer within an implementation object. */
+#define ICOM_VFIELD_OFFSET(impltype, iface) \
+	offsetof(impltype, ICOM_VFIELD_MULTI_NAME(iface))
+
+/* Given an interface pointer, returns the implementation pointer. */
+#define ICOM_OBJECT(impltype, ifacename, ifaceptr)		\
+	(impltype*)((ifaceptr) == NULL ? NULL			\
+		  : (char*)(ifaceptr) - ICOM_VFIELD_OFFSET(impltype,ifacename))
+
+#define ICOM_THIS_FROM(impltype, ifacename, ifaceptr) \
+	impltype* This = ICOM_OBJECT(impltype, ifacename, ifaceptr)
+
+/* Given an object and interface name, returns a pointer to that interface. */
+#define ICOM_INTERFACE(implobj, iface) \
+	(&((implobj)->ICOM_VFIELD_MULTI_NAME(iface)))
+
+#define ICOM_INIT_INTERFACE(implobj, ifacename, vtblname) \
+	do { \
+	  (implobj)->ICOM_VFIELD_MULTI_NAME(ifacename).lpVtbl = &(vtblname); \
+	} while (0)
+
+#define COM_INTERFACE_CAST(impltype, ifnamefrom, ifnameto, ifaceptr)	\
+	ICOM_INTERFACE(ICOM_OBJECT(impltype, ifnamefrom, ifaceptr), ifnameto)
diff --git a/dlls/ddraw/ddraw.spec b/dlls/ddraw/ddraw.spec
index 588822c..1682fa7 100644
--- a/dlls/ddraw/ddraw.spec
+++ b/dlls/ddraw/ddraw.spec
@@ -1,5 +1,6 @@
 name ddraw
 type win32
+init DDRAW_DllMain
 
 import user32.dll
 import x11drv.dll
diff --git a/dlls/ddraw/ddraw/dga.c b/dlls/ddraw/ddraw/dga.c
deleted file mode 100644
index 1695ea3..0000000
--- a/dlls/ddraw/ddraw/dga.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*		DirectDraw IDirectDraw XF86DGA interface
- *
- * Copyright 1997-2000 Marcus Meissner
- * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
- */
-/* XF86DGA:
- * When DirectVideo mode is enabled you can no longer use 'normal' X 
- * applications nor can you switch to a virtual console. Also, enabling
- * only works, if you have switched to the screen where the application
- * is running.
- * Some ways to debug this stuff are:
- * - A terminal connected to the serial port. Can be bought used for cheap.
- *   (This is the method I am using.)
- * - Another machine connected over some kind of network.
- */
-
-/*
- * This file contains the XF86 DGA specific interface functions.
- * We are 'allowed' to call X11 specific IDirectDraw functions.
- */
-
-#include "config.h"
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "winerror.h"
-#include "wine/exception.h"
-#include "ddraw.h"
-#include "d3d.h"
-#include "debugtools.h"
-#include "options.h"
-
-#define RESTORE_SIGNALS
-
-DEFAULT_DEBUG_CHANNEL(ddraw);
-
-#include "dga_private.h"
-
-struct ICOM_VTABLE(IDirectDraw)		dga_ddvt;
-struct ICOM_VTABLE(IDirectDraw2)	dga_dd2vt;
-struct ICOM_VTABLE(IDirectDraw4)	dga_dd4vt;
-struct ICOM_VTABLE(IDirectDraw7)	dga_dd7vt;
-
-#define DDPRIVATE(x) dga_dd_private *ddpriv = ((dga_dd_private*)(x)->d->private)
-#define DPPRIVATE(x) dga_dp_private *dppriv = ((dga_dp_private*)(x)->private)
-
-/*******************************************************************************
- *				IDirectDraw
- */
-
-/* This function is used both by DGA and DGA2 drivers, thus the virtual function table
-   is not set here, but in the calling function */
-HRESULT WINAPI DGA_IDirectDraw2Impl_CreateSurface_with_VT(
-    LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,
-    IUnknown *lpunk, void *vtable
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    IDirectDrawSurfaceImpl* dsurf;
-    DDPRIVATE(This);
-    dga_ds_private *dspriv;
-    int	i, fbheight = ddpriv->fb_height;
-
-    TRACE("(%p)->(%p,%p,%p)\n",This,lpddsd,lpdsf,lpunk);
-    if (TRACE_ON(ddraw)) _dump_surface_desc(lpddsd);
-
-    *lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(
-    	GetProcessHeap(),
-	HEAP_ZERO_MEMORY,
-	sizeof(IDirectDrawSurfaceImpl)
-    );
-    dsurf = *(IDirectDrawSurfaceImpl**)lpdsf;
-    dsurf->private = (dga_ds_private*)HeapAlloc(
-	GetProcessHeap(),
-	HEAP_ZERO_MEMORY,
-	sizeof(dga_ds_private)
-    );
-    ICOM_VTBL(dsurf) = (ICOM_VTABLE(IDirectDrawSurface)*)vtable;
-
-    dspriv = (dga_ds_private*)dsurf->private;
-    IDirectDraw2_AddRef(iface);
-
-    dsurf->ref = 1;
-    dsurf->s.ddraw = This;
-    dsurf->s.palette = NULL;
-    dspriv->fb_height = -1; /* This is to have non-on screen surfaces freed */
-    dsurf->s.lpClipper = NULL;
-
-    /* Copy the surface description */
-    dsurf->s.surface_desc = *lpddsd;
-
-    if (!(lpddsd->dwFlags & DDSD_WIDTH))
-	dsurf->s.surface_desc.dwWidth  = This->d->width;
-    if (!(lpddsd->dwFlags & DDSD_HEIGHT))
-	dsurf->s.surface_desc.dwHeight = This->d->height;
-
-    dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
-
-    /* Check if this a 'primary surface' or not */
-    if ((lpddsd->dwFlags & DDSD_CAPS) &&
-	(lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
-	/* This is THE primary surface => there is DGA-specific code */
-
-	/* Find a viewport */
-	for (i=0;i<32;i++)
-	    if (!(ddpriv->vpmask & (1<<i)))
-		break;
-	TRACE("using viewport %d for a primary surface\n",i);
-	/* if i == 32 or maximum ... return error */
-	ddpriv->vpmask|=(1<<i);
-	lpddsd->lPitch = dsurf->s.surface_desc.lPitch = 
-		ddpriv->fb_width*PFGET_BPP(This->d->directdraw_pixelformat);
-
-	dsurf->s.surface_desc.u1.lpSurface =
-	    ddpriv->fb_addr + i*fbheight*lpddsd->lPitch;
-
-	dspriv->fb_height = i*fbheight;
-
-	/* Add flags if there were not present */
-	dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
-	dsurf->s.surface_desc.dwWidth = This->d->width;
-	dsurf->s.surface_desc.dwHeight = This->d->height;
-	TRACE("primary surface: dwWidth=%ld, dwHeight=%ld, lPitch=%ld\n",This->d->width,This->d->height,lpddsd->lPitch);
-	/* We put our surface always in video memory */
-	SDDSCAPS(dsurf) |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
-	dsurf->s.surface_desc.ddpfPixelFormat = This->d->directdraw_pixelformat;
-	dsurf->s.chain = NULL;
-
-	if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
-	    IDirectDrawSurface4Impl*	back;
-	    dga_ds_private		*bspriv;
-	    int	bbc;
-
-	    for (bbc=lpddsd->dwBackBufferCount;bbc--;) {
-	        int i;
-	      
-		back = (IDirectDrawSurface4Impl*)HeapAlloc(
-		    GetProcessHeap(),
-		    HEAP_ZERO_MEMORY,
-		    sizeof(IDirectDrawSurface4Impl)
-		);
-		IDirectDraw2_AddRef(iface);
-		back->ref = 1;
-		ICOM_VTBL(back) = (ICOM_VTABLE(IDirectDrawSurface4)*)vtable;
-		back->private = HeapAlloc(
-			GetProcessHeap(),
-			HEAP_ZERO_MEMORY,
-			sizeof(dga_ds_private)
-		);
-		bspriv = (dga_ds_private*)back->private;
-
-		for (i=0;i<32;i++)
-		    if (!(ddpriv->vpmask & (1<<i)))
-			break;
-		TRACE("using viewport %d for backbuffer %d\n",i, bbc);
-		/* if i == 32 or maximum ... return error */
-		ddpriv->vpmask|=(1<<i);
-
-		bspriv->fb_height = i*fbheight;
-		/* Copy the surface description from the front buffer */
-		back->s.surface_desc = dsurf->s.surface_desc;
-		/* Change the parameters that are not the same */
-		back->s.surface_desc.u1.lpSurface =
-		    ddpriv->fb_addr + i*fbheight*lpddsd->lPitch;
-
-		back->s.ddraw = This;
-		/* Add relevant info to front and back buffers */
-		/* FIXME: backbuffer/frontbuffer handling broken here, but
-		 * will be fixed up in _Flip().
-		 */
-		SDDSCAPS(dsurf) |= DDSCAPS_FRONTBUFFER;
-		SDDSCAPS(back) |= DDSCAPS_FLIP|DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY;
-		back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
-		SDDSCAPS(back) &= ~(DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE);
-		IDirectDrawSurface4_AddAttachedSurface((LPDIRECTDRAWSURFACE4)(*lpdsf),(LPDIRECTDRAWSURFACE4)back);
-	    }
-	}
-    } else {
-	/* There is no DGA-specific code here...
-	 * Go to the common surface creation function
-	 */
-	return common_off_screen_CreateSurface(This, dsurf);
-    }
-    return DD_OK;
-}
-
-static HRESULT WINAPI DGA_IDirectDraw2Impl_CreateSurface(
-    LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,
-    IUnknown *lpunk
-) {
-  HRESULT ret;
-
-  ret = DGA_IDirectDraw2Impl_CreateSurface_with_VT(iface, lpddsd, lpdsf, lpunk, &dga_dds4vt);
-
-  return ret;
-}
-
-
-static HRESULT WINAPI DGA_IDirectDrawImpl_SetDisplayMode(
-    LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
-) {
-    ICOM_THIS(IDirectDrawImpl,iface);
-    DDPRIVATE(This);
-
-    TRACE("(%p)->(%ld,%ld,%ld)\n", This, width, height, depth);
-
-    /* We hope getting the asked for depth */
-    if ( _common_depth_to_pixelformat(depth,iface) !=  -1 ) {
-	/* I.e. no visual found or emulated */
-	ERR("(w=%ld,h=%ld,d=%ld), unsupported depth!\n",width,height,depth);
-	return DDERR_UNSUPPORTEDMODE;
-    }
-
-    if (This->d->width < width) {
-	ERR("SetDisplayMode(w=%ld,h=%ld,d=%ld), width %ld exceeds framebuffer width %ld\n",width,height,depth,width,This->d->width);
-	return DDERR_UNSUPPORTEDMODE;
-    }
-    This->d->width	= width;
-    This->d->height	= height;
-
-    /* adjust fb_height, so we don't overlap */
-    if (ddpriv->fb_height < height)
-	ddpriv->fb_height = height;
-    _common_IDirectDrawImpl_SetDisplayMode(This);
-
-    xf86vmode_setdisplaymode(width,height);
-
-    /* FIXME: this function OVERWRITES several signal handlers. 
-     * can we save them? and restore them later? In a way that
-     * it works for the library too?
-     */
-    TSXF86DGADirectVideo(display,DefaultScreen(display),XF86DGADirectGraphics);
-    TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
-
-#ifdef RESTORE_SIGNALS
-    SIGNAL_Init();
-#endif
-    return DD_OK;
-}
-
-HRESULT WINAPI DGA_IDirectDraw2Impl_GetCaps(
-    LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDPRIVATE(This);
-
-    TRACE("(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
-    if (!caps1 && !caps2)
-       return DDERR_INVALIDPARAMS;
-    if (caps1) {
-	caps1->dwVidMemTotal = ddpriv->fb_memsize;
-	caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED);		/* we can do anything */
-	caps1->ddsCaps.dwCaps = 0xffffffff;	/* we can do anything */
-    }
-    if (caps2) {
-	caps2->dwVidMemTotal = ddpriv->fb_memsize;
-	caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED);		/* we can do anything */
-	caps2->ddsCaps.dwCaps = 0xffffffff;	/* we can do anything */
-    }
-    return DD_OK;
-}
-
-#if 0 /* Not used as of now.... */
-static void fill_caps(LPDDCAPS caps) {
-    /* This function tries to fill the capabilities of Wine's DDraw
-     * implementation. Needs to be fixed, though.. */
-    if (caps == NULL)
-	return;
-
-    caps->dwSize = sizeof(*caps);
-    caps->dwCaps = DDCAPS_ALPHA | DDCAPS_BLT | DDCAPS_BLTSTRETCH | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL | DDCAPS_CANBLTSYSMEM |  DDCAPS_COLORKEY | DDCAPS_PALETTE /*| DDCAPS_NOHARDWARE*/;
-    caps->dwCaps2 = DDCAPS2_CERTIFIED | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_WIDESURFACES;
-    caps->dwCKeyCaps = 0xFFFFFFFF; /* Should put real caps here one day... */
-    caps->dwFXCaps = 0;
-    caps->dwFXAlphaCaps = 0;
-    caps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
-    caps->dwSVCaps = 0;
-    caps->dwZBufferBitDepths = DDBD_16;
-    /* I put here 8 Mo so that D3D applications will believe they have enough
-     * memory to put textures in video memory.
-     * BTW, is this only frame buffer memory or also texture memory (for Voodoo
-     * boards for example) ?
-     */
-    caps->dwVidMemTotal = 8192 * 1024;
-    caps->dwVidMemFree = 8192 * 1024;
-    /* These are all the supported capabilities of the surfaces */
-    caps->ddsCaps.dwCaps = DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
-    DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
-      /*DDSCAPS_OVERLAY |*/ DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
-	DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
-#ifdef HAVE_OPENGL
-    caps->dwCaps |= DDCAPS_3D | DDCAPS_ZBLTS;
-    caps->dwCaps2 |=  DDCAPS2_NO2DDURING3DSCENE;
-    caps->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
-#endif
-}
-#endif
-
-static HRESULT WINAPI DGA_IDirectDraw2Impl_CreatePalette(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    IDirectDrawPaletteImpl*	ddpal;
-    dga_dp_private		*dppriv;
-    HRESULT			res;
-    int 			xsize = 0,i;
-
-    TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,lpddpal,lpunk);
-    res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,(IDirectDrawPaletteImpl**)lpddpal,lpunk,&xsize);
-    if (res != 0)
-	return res;
-    ddpal = *(IDirectDrawPaletteImpl**)lpddpal;
-    ddpal->private = HeapAlloc(
-	GetProcessHeap(),
-	HEAP_ZERO_MEMORY,
-	sizeof(dga_dp_private)
-    );
-    dppriv = (dga_dp_private*)ddpal->private;
-
-    ICOM_VTBL(ddpal)= &dga_ddpalvt;
-    if (This->d->directdraw_pixelformat.u.dwRGBBitCount<=8) {
-	dppriv->cm = TSXCreateColormap(display,DefaultRootWindow(display),DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
-    } else {
-	ERR("why are we doing CreatePalette in hi/truecolor?\n");
-	dppriv->cm = 0;
-    }
-    if (dppriv->cm && xsize) {
-	for (i=0;i<xsize;i++) {
-	    XColor xc;
-
-	    xc.red = ddpal->palents[i].peRed<<8;
-	    xc.blue = ddpal->palents[i].peBlue<<8;
-	    xc.green = ddpal->palents[i].peGreen<<8;
-	    xc.flags = DoRed|DoBlue|DoGreen;
-	    xc.pixel = i;
-	    TSXStoreColor(display,dppriv->cm,&xc);
-	}
-    }
-    return DD_OK;
-}
-
-static HRESULT WINAPI DGA_IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    TRACE("(%p)->()\n",This);
-    Sleep(1000);
-    TSXF86DGADirectVideo(display,DefaultScreen(display),0);
-#ifdef RESTORE_SIGNALS
-    SIGNAL_Init();
-#endif
-    return DD_OK;
-}
-
-static ULONG WINAPI DGA_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDPRIVATE(This);
-    TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
-
-    if (!--(This->ref)) {
-      if (!--(This->d->ref)) {
-	  VirtualFree(ddpriv->fb_addr, 0, MEM_RELEASE);
-	  TSXF86DGADirectVideo(display,DefaultScreen(display),0);
-	  if (This->d->window && GetPropA(This->d->window,ddProp))
-	    DestroyWindow(This->d->window);
-
-	  xf86vmode_restore();
-
-#ifdef RESTORE_SIGNALS
-	  SIGNAL_Init();
-#endif
-	  HeapFree(GetProcessHeap(),0,This->d);
-      }
-      HeapFree(GetProcessHeap(),0,This);
-      return S_OK;
-    }
-    return This->ref;
-}
-
-HRESULT WINAPI DGA_IDirectDraw2Impl_QueryInterface(
-    LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-
-    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
-    if ( IsEqualGUID( &IID_IUnknown, refiid ) ) {
-	*obj = This;
-	IDirectDraw2_AddRef(iface);
-
-	TRACE("  Creating IUnknown interface (%p)\n", *obj);
-	
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirectDraw, refiid ) ) {
-	IDirectDrawImpl	*dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
-	ICOM_VTBL(dd) = &dga_ddvt;dd->ref = 1;dd->d = This->d;This->d++;
-	*obj = dd;
-
-	IDirectDraw2_AddRef(iface);
-	TRACE("  Creating IDirectDraw interface (%p)\n", *obj);
-	
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) ) {
-	IDirectDraw2Impl	*dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
-	ICOM_VTBL(dd) = &dga_dd2vt;dd->ref = 1;dd->d = This->d;This->d++;
-	*obj = dd;
-
-	IDirectDraw2_AddRef(iface);
-	TRACE("  Creating IDirectDraw2 interface (%p)\n", *obj);
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) ) {
-	IDirectDraw4Impl	*dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
-	ICOM_VTBL(dd) = &dga_dd4vt;dd->ref = 1;dd->d = This->d;This->d++;
-	*obj = dd;
-
-	IDirectDraw4_AddRef(iface);
-	TRACE("  Creating IDirectDraw4 interface (%p)\n", *obj);
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirectDraw7, refiid ) ) {
-	IDirectDraw4Impl	*dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
-	ICOM_VTBL(dd) = (ICOM_VTABLE(IDirectDraw4)*)&dga_dd7vt;dd->ref = 1;dd->d = This->d;This->d++;
-	*obj = dd;
-
-	IDirectDraw7_AddRef(iface);
-	FIXME("  Creating IDirectDraw7 interface (by using DirectDraw4 impl.) (%p)\n", *obj);
-	return S_OK;
-    }
-    FIXME("(%p):interface for IID %s _NOT_ found!\n",This,debugstr_guid(refiid));
-    return OLE_E_ENUM_NOMORE;
-}
-
-static HRESULT WINAPI DGA_IDirectDraw2Impl_EnumDisplayModes(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDSURFACEDESC	ddsfd;
-    static struct {
-	    int w,h;
-    } modes[5] = { /* some usual modes */
-	{512,384},
-	{640,400},
-	{640,480},
-	{800,600},
-	{1024,768},
-    };
-    static int depths[4] = {8,16,24,32};
-    int	i,j;
-
-    TRACE("(%p)->(0x%08lx,%p,%p,%p)\n",This,dwFlags,lpddsfd,context,modescb);
-    ddsfd.dwSize = sizeof(ddsfd);
-    ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
-    if (dwFlags & DDEDM_REFRESHRATES) {
-	    ddsfd.dwFlags |= DDSD_REFRESHRATE;
-	    ddsfd.u.dwRefreshRate = 60;
-    }
-    ddsfd.ddsCaps.dwCaps = 0;
-    ddsfd.dwBackBufferCount = 1;
-
-    for (i=0;i<sizeof(depths)/sizeof(depths[0]);i++) {
-      ddsfd.dwBackBufferCount = 1;
-      ddsfd.ddpfPixelFormat.dwFourCC	= 0;
-      ddsfd.ddpfPixelFormat.dwFlags 	= DDPF_RGB;
-      ddsfd.ddpfPixelFormat.u.dwRGBBitCount	= depths[i];
-      /* FIXME: those masks would have to be set in depth > 8 */
-      if (depths[i]==8) {
-	ddsfd.ddpfPixelFormat.u1.dwRBitMask  	= 0;
-	ddsfd.ddpfPixelFormat.u2.dwGBitMask  	= 0;
-	ddsfd.ddpfPixelFormat.u3.dwBBitMask 	= 0;
-	ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
-	ddsfd.ddsCaps.dwCaps=DDSCAPS_PALETTE;
-	ddsfd.ddpfPixelFormat.dwFlags|=DDPF_PALETTEINDEXED8;
-      } else {
-	ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
-	
-	/* FIXME: We should query those from X itself */
-	switch (depths[i]) {
-	case 16:
-	  ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0xF800;
-	  ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x07E0;
-	  ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x001F;
-	  break;
-	case 24:
-	  ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0x00FF0000;
-	  ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x0000FF00;
-	  ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x000000FF;
-	  break;
-	case 32:
-	  ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0x00FF0000;
-	  ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x0000FF00;
-	  ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x000000FF;
-	  break;
-	}
-      }
-      
-      ddsfd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
-      ddsfd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
-      TRACE(" enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
-      if (!modescb(&ddsfd,context)) return DD_OK;
-      
-      for (j=0;j<sizeof(modes)/sizeof(modes[0]);j++) {
-	ddsfd.dwWidth	= modes[j].w;
-	ddsfd.dwHeight	= modes[j].h;
-	TRACE(" enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
-	if (!modescb(&ddsfd,context)) return DD_OK;
-      }
-      
-      if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
-	/* modeX is not standard VGA */
-	
-	ddsfd.dwHeight = 200;
-	ddsfd.dwWidth = 320;
-	TRACE(" enumerating (320x200x%d)\n",depths[i]);
-	if (!modescb(&ddsfd,context)) return DD_OK;
-      }
-    }
-
-    return DD_OK;
-}
-
-HRESULT WINAPI DGA_IDirectDraw2Impl_GetDisplayMode(
-	LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDPRIVATE(This);
-
-    TRACE("(%p)->(%p)\n",This,lpddsfd);
-    lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
-    lpddsfd->dwHeight = This->d->height;
-    lpddsfd->dwWidth = This->d->width;
-    lpddsfd->lPitch = ddpriv->fb_width*PFGET_BPP(This->d->directdraw_pixelformat);
-    lpddsfd->dwBackBufferCount = 2;
-    lpddsfd->u.dwRefreshRate = 60;
-    lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
-    lpddsfd->ddpfPixelFormat = This->d->directdraw_pixelformat;
-    if (TRACE_ON(ddraw))
-	_dump_surface_desc(lpddsfd);
-    return DD_OK;
-}
-
-/* Note: Hack so we can reuse the old functions without compiler warnings */
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)	(typeof(dga_ddvt.fn##fun))
-#else
-# define XCAST(fun)	(void *)
-#endif
-
-struct ICOM_VTABLE(IDirectDraw) dga_ddvt = 
-{
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
-    XCAST(AddRef)IDirectDraw2Impl_AddRef,
-    XCAST(Release)DGA_IDirectDraw2Impl_Release,
-    XCAST(Compact)IDirectDraw2Impl_Compact,
-    XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
-    XCAST(CreatePalette)DGA_IDirectDraw2Impl_CreatePalette,
-    XCAST(CreateSurface)DGA_IDirectDraw2Impl_CreateSurface,
-    XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
-    XCAST(EnumDisplayModes)DGA_IDirectDraw2Impl_EnumDisplayModes,
-    XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
-    XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
-    XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
-    XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
-    XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
-    XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
-    XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
-    XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
-    XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
-    XCAST(Initialize)IDirectDraw2Impl_Initialize,
-    XCAST(RestoreDisplayMode)DGA_IDirectDraw2Impl_RestoreDisplayMode,
-    XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
-    DGA_IDirectDrawImpl_SetDisplayMode,
-    XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
-};
-#undef XCAST
-
-/*****************************************************************************
- * 	IDirectDraw2
- *
- */
-
-static HRESULT WINAPI DGA_IDirectDraw2Impl_SetDisplayMode(
-    LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD dwRefreshRate, DWORD dwFlags
-) {
-    FIXME( "Ignored parameters (0x%08lx,0x%08lx)\n", dwRefreshRate, dwFlags ); 
-    return DGA_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
-}
-
-HRESULT WINAPI DGA_IDirectDraw2Impl_GetAvailableVidMem(
-    LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDPRIVATE(This);
-
-    TRACE("(%p)->(%p,%p,%p)\n",This,ddscaps,total,free);
-    if (total) *total = ddpriv->fb_memsize * 1024;
-    if (free) *free = ddpriv->fb_memsize * 1024;
-    return DD_OK;
-}
-
-ICOM_VTABLE(IDirectDraw2) dga_dd2vt = 
-{
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    DGA_IDirectDraw2Impl_QueryInterface,
-    IDirectDraw2Impl_AddRef,
-    DGA_IDirectDraw2Impl_Release,
-    IDirectDraw2Impl_Compact,
-    IDirectDraw2Impl_CreateClipper,
-    DGA_IDirectDraw2Impl_CreatePalette,
-    DGA_IDirectDraw2Impl_CreateSurface,
-    IDirectDraw2Impl_DuplicateSurface,
-    DGA_IDirectDraw2Impl_EnumDisplayModes,
-    IDirectDraw2Impl_EnumSurfaces,
-    IDirectDraw2Impl_FlipToGDISurface,
-    DGA_IDirectDraw2Impl_GetCaps,
-    DGA_IDirectDraw2Impl_GetDisplayMode,
-    IDirectDraw2Impl_GetFourCCCodes,
-    IDirectDraw2Impl_GetGDISurface,
-    IDirectDraw2Impl_GetMonitorFrequency,
-    IDirectDraw2Impl_GetScanLine,
-    IDirectDraw2Impl_GetVerticalBlankStatus,
-    IDirectDraw2Impl_Initialize,
-    DGA_IDirectDraw2Impl_RestoreDisplayMode,
-    IDirectDraw2Impl_SetCooperativeLevel,
-    DGA_IDirectDraw2Impl_SetDisplayMode,
-    IDirectDraw2Impl_WaitForVerticalBlank,
-    DGA_IDirectDraw2Impl_GetAvailableVidMem
-};
-
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)	(typeof(dga_dd4vt.fn##fun))
-#else
-# define XCAST(fun)	(void*)
-#endif
-
-ICOM_VTABLE(IDirectDraw4) dga_dd4vt = 
-{
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
-    XCAST(AddRef)IDirectDraw2Impl_AddRef,
-    XCAST(Release)DGA_IDirectDraw2Impl_Release,
-    XCAST(Compact)IDirectDraw2Impl_Compact,
-    XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
-    XCAST(CreatePalette)DGA_IDirectDraw2Impl_CreatePalette,
-    XCAST(CreateSurface)DGA_IDirectDraw2Impl_CreateSurface,
-    XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
-    XCAST(EnumDisplayModes)DGA_IDirectDraw2Impl_EnumDisplayModes,
-    XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
-    XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
-    XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
-    XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
-    XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
-    XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
-    XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
-    XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
-    XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
-    XCAST(Initialize)IDirectDraw2Impl_Initialize,
-    XCAST(RestoreDisplayMode)DGA_IDirectDraw2Impl_RestoreDisplayMode,
-    XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
-    XCAST(SetDisplayMode)DGA_IDirectDrawImpl_SetDisplayMode,
-    XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
-    XCAST(GetAvailableVidMem)DGA_IDirectDraw2Impl_GetAvailableVidMem,
-    IDirectDraw4Impl_GetSurfaceFromDC,
-    IDirectDraw4Impl_RestoreAllSurfaces,
-    IDirectDraw4Impl_TestCooperativeLevel,
-    IDirectDraw4Impl_GetDeviceIdentifier
-};
-#undef XCAST
-
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)	(typeof(dga_dd7vt.fn##fun))
-#else
-# define XCAST(fun)	(void*)
-#endif
-
-ICOM_VTABLE(IDirectDraw7) dga_dd7vt = 
-{
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
-    XCAST(AddRef)IDirectDraw2Impl_AddRef,
-    XCAST(Release)DGA_IDirectDraw2Impl_Release,
-    XCAST(Compact)IDirectDraw2Impl_Compact,
-    XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
-    XCAST(CreatePalette)DGA_IDirectDraw2Impl_CreatePalette,
-    XCAST(CreateSurface)DGA_IDirectDraw2Impl_CreateSurface,
-    XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
-    XCAST(EnumDisplayModes)DGA_IDirectDraw2Impl_EnumDisplayModes,
-    XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
-    XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
-    XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
-    XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
-    XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
-    XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
-    XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
-    XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
-    XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
-    XCAST(Initialize)IDirectDraw2Impl_Initialize,
-    XCAST(RestoreDisplayMode)DGA_IDirectDraw2Impl_RestoreDisplayMode,
-    XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
-    XCAST(SetDisplayMode)DGA_IDirectDrawImpl_SetDisplayMode,
-    XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
-    XCAST(GetAvailableVidMem)DGA_IDirectDraw2Impl_GetAvailableVidMem,
-    XCAST(GetSurfaceFromDC)IDirectDraw4Impl_GetSurfaceFromDC,
-    XCAST(RestoreAllSurfaces)IDirectDraw4Impl_RestoreAllSurfaces,
-    XCAST(TestCooperativeLevel)IDirectDraw4Impl_TestCooperativeLevel,
-    XCAST(GetDeviceIdentifier)IDirectDraw4Impl_GetDeviceIdentifier,
-    IDirectDraw7Impl_StartModeTest,
-    IDirectDraw7Impl_EvaluateMode
-};
-#undef XCAST
diff --git a/dlls/ddraw/ddraw/dga2.c b/dlls/ddraw/ddraw/dga2.c
index 88f2665..fabc2af 100644
--- a/dlls/ddraw/ddraw/dga2.c
+++ b/dlls/ddraw/ddraw/dga2.c
@@ -1,431 +1,407 @@
-/*		DirectDraw IDirectDraw XF86DGA interface
+/*	DirectDraw driver for XF86DGA2 primary surface
  *
- *  DGA2's specific IDirectDraw functions...
+ * Copyright 2000 TransGaming Technologies Inc.
  */
 
 #include "config.h"
 
-#include <unistd.h>
-#include <fcntl.h>
+#ifdef HAVE_LIBXXF86DGA2
+
+#include "debugtools.h"
+#include "ts_xlib.h"
+#include "ts_xf86dga2.h"
+#include "x11drv.h"
+#include <ddraw.h>
+
 #include <assert.h>
-#include <string.h>
-#include <stdio.h>
 #include <stdlib.h>
 
-#include "winerror.h"
-#include "wine/exception.h"
-#include "ddraw.h"
-#include "d3d.h"
-#include "debugtools.h"
-#include "message.h"
+#include "ddraw_private.h"
+#include "ddraw/main.h"
+#include "ddraw/user.h"
+#include "ddraw/dga2.h"
+#include "dclipper/main.h"
+#include "dpalette/main.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/user.h"
+#include "dsurface/dga2.h"
+
 #include "options.h"
 
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
-#include "dga2_private.h"
+static ICOM_VTABLE(IDirectDraw7) XF86DGA2_DirectDraw_VTable;
 
-struct ICOM_VTABLE(IDirectDraw)		dga2_ddvt;
-struct ICOM_VTABLE(IDirectDraw2)	dga2_dd2vt;
-struct ICOM_VTABLE(IDirectDraw4)	dga2_dd4vt;
+static const DDDEVICEIDENTIFIER2 xf86dga2_device = 
+{
+    "XF86DGA2 Driver",
+    "WINE DirectDraw on XF86DGA2",
+    { { 0x00010001, 0x00010001 } },
+    0, 0, 0, 0,
+    /* e2dcb020-dc60-11d1-8407-9714f5d50803 */
+    {0xe2dcb020,0xdc60,0x11d1,{0x84,0x07,0x97,0x14,0xf5,0xd5,0x08,0x03}},
+    0
+};
 
-#define DDPRIVATE(x) dga2_dd_private *ddpriv = ((dga2_dd_private*)(x)->d->private)
-#define DPPRIVATE(x) dga2_dp_private *dppriv = ((dga2_dp_private*)(x)->private)
+HRESULT XF86DGA2_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+				   IUnknown* pUnkOuter, BOOL ex);
+HRESULT XF86DGA2_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
 
-/*******************************************************************************
- *				IDirectDraw
- */
-static HRESULT WINAPI DGA2_IDirectDraw2Impl_CreateSurface(
-    LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,
-    IUnknown *lpunk
-) {
-  HRESULT ret;
+static const ddraw_driver xf86dga2_driver =
+{
+    &xf86dga2_device,
+    20, /* XVidMode is 11 */
+    XF86DGA2_DirectDraw_Create,
+    XF86DGA2_DirectDraw_Initialize
+};
 
-  ret = DGA_IDirectDraw2Impl_CreateSurface_with_VT(iface, lpddsd, lpdsf, lpunk, &dga2_dds4vt);
+static XDGAMode* modes;
+static DWORD num_modes;
+static int dga_event, dga_error;
 
-  return ret;
-}
+/* Called from DllInit, which is synchronised so there are no threading
+ * concerns. */
+static BOOL initialize(void)
+{
+    int nmodes;
+    int major, minor;
 
-static HRESULT WINAPI DGA2_IDirectDraw2Impl_SetCooperativeLevel(
-    LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel
-) {
-    /* ICOM_THIS(IDirectDraw2Impl,iface); */
-    HRESULT ret;
-    int evbase, erbase;
+    if (X11DRV_GetXRootWindow() != DefaultRootWindow(display)) return FALSE;
 
-    ret = IDirectDraw2Impl_SetCooperativeLevel(iface, hwnd, cooplevel);
+    /* FIXME: don't use PROFILE calls */
+    if (!PROFILE_GetWineIniBool("x11drv", "UseDGA", 1)) return FALSE;
 
-    if (ret != DD_OK)
-      return ret;
+    if (!TSXDGAQueryExtension(display, &dga_event, &dga_error)) return FALSE;
 
-    TSXDGAQueryExtension(display, &evbase, &erbase);
+    if (!TSXDGAQueryVersion(display, &major, &minor)) return FALSE;
+
+    if (major < 2) return FALSE; /* only bother with DGA2 */
+
+    /* test that it works */
+    if (!TSXDGAOpenFramebuffer(display, DefaultScreen(display))) {
+	TRACE("disabling XF86DGA2 (insufficient permissions?)\n");
+	return FALSE;
+    }
+    TSXDGACloseFramebuffer(display, DefaultScreen(display));
     
-    /* Now, start handling of DGA events giving the handle to the DDraw window
-       as the window for which the event will be reported */
-    TSXDGASelectInput(display, DefaultScreen(display),
-		      KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask );
-    X11DRV_EVENT_SetDGAStatus(hwnd, evbase);
-    return DD_OK;
+    TRACE("getting XF86DGA2 mode list\n");
+    modes = TSXDGAQueryModes(display, DefaultScreen(display), &nmodes);
+    if (!modes) return FALSE;
+    num_modes = nmodes;
+
+    TRACE("enabling XF86DGA2\n");
+
+    return TRUE;
 }
 
-void _DGA2_Initialize_FrameBuffer(IDirectDrawImpl *This, int mode) {
-    DDPIXELFORMAT *pf = &(This->d->directdraw_pixelformat);
-    DDPRIVATE(This);
-
-    /* Now, get the device / mode description */
-    ddpriv->dev = TSXDGASetMode(display, DefaultScreen(display), mode);
-
-    ddpriv->DGA.fb_width = ddpriv->dev->mode.imageWidth;
-    TSXDGASetViewport(display,DefaultScreen(display),0,0, XDGAFlipImmediate);
-    ddpriv->DGA.fb_height = ddpriv->dev->mode.viewportHeight;
-    TRACE("video framebuffer: begin %p, width %d, memsize %d\n",
-	ddpriv->dev->data,
-	ddpriv->dev->mode.imageWidth,
-	(ddpriv->dev->mode.imageWidth *
-	 ddpriv->dev->mode.imageHeight *
-	 (ddpriv->dev->mode.bitsPerPixel / 8))
-    );
-    TRACE("viewport height: %d\n", ddpriv->dev->mode.viewportHeight);
-    /* Get the screen dimensions as seen by Wine.
-     * In that case, it may be better to ignore the -desktop mode and return the
-     * real screen size => print a warning */
-    This->d->height = GetSystemMetrics(SM_CYSCREEN);
-    This->d->width = GetSystemMetrics(SM_CXSCREEN);
-    ddpriv->DGA.fb_addr = ddpriv->dev->data;
-    ddpriv->DGA.fb_memsize = (ddpriv->dev->mode.imageWidth *
-			      ddpriv->dev->mode.imageHeight *
-			      (ddpriv->dev->mode.bitsPerPixel / 8));
-    ddpriv->DGA.vpmask = 0;
-
-    /* Fill the screen pixelformat */
-    pf->dwSize = sizeof(DDPIXELFORMAT);
-    pf->dwFourCC = 0;
-    pf->u.dwRGBBitCount = ddpriv->dev->mode.bitsPerPixel;
-    if (ddpriv->dev->mode.depth == 8) {
-	pf->dwFlags = DDPF_PALETTEINDEXED8|DDPF_RGB;
-	pf->u1.dwRBitMask = 0;
-	pf->u2.dwGBitMask = 0;
-	pf->u3.dwBBitMask = 0;
-    } else {
-	pf->dwFlags = DDPF_RGB;
-	pf->u1.dwRBitMask = ddpriv->dev->mode.redMask;
-	pf->u2.dwGBitMask = ddpriv->dev->mode.greenMask;
-	pf->u3.dwBBitMask = ddpriv->dev->mode.blueMask;
-    }
-    pf->u4.dwRGBAlphaBitMask= 0;
-    This->d->screen_pixelformat = *pf; 
+static void cleanup(void)
+{
+    TSXFree(modes);
 }
 
-static HRESULT WINAPI DGA2_IDirectDrawImpl_SetDisplayMode(
-    LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
-) {
-    ICOM_THIS(IDirectDrawImpl,iface);
-    DDPRIVATE(This);
-    int	i;
-    XDGAMode *modes = ddpriv->modes;
-    int mode_to_use = -1;
+static XDGAMode* choose_mode(DWORD dwWidth, DWORD dwHeight,
+		       DWORD dwRefreshRate, DWORD dwFlags)
+{
+    XDGAMode* best = NULL;
+    int i;
 
-    TRACE("(%p)->(%ld,%ld,%ld)\n", This, width, height, depth);
-
-    /* Search in the list a display mode that corresponds to what is requested */
-    for (i = 0; i < ddpriv->num_modes; i++) {
-      if ((height == modes[i].viewportHeight) &&
-	  (width == modes[i].viewportWidth) &&
-	  (depth == modes[i].depth)
-	  )
-	mode_to_use = modes[i].num;
-    }
-    
-    if (mode_to_use < 0) {
-      ERR("Could not find matching mode !!!\n");
-      return DDERR_UNSUPPORTEDMODE;
-    } else {
-      TRACE("Using mode number %d\n", mode_to_use);
-      
-      VirtualFree(ddpriv->DGA.fb_addr, 0, MEM_RELEASE);
-      TSXDGACloseFramebuffer(display, DefaultScreen(display));
-      
-      if (!TSXDGAOpenFramebuffer(display, DefaultScreen(display))) {
-	ERR("Error opening the frame buffer !!!\n");
-	return DDERR_GENERIC;
-      }
-      
-      /* Initialize the frame buffer */
-      _DGA2_Initialize_FrameBuffer(This, mode_to_use);
-      VirtualAlloc(ddpriv->DGA.fb_addr, ddpriv->DGA.fb_memsize, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
-      
-      /* Re-get (if necessary) the DGA events */
-      TSXDGASelectInput(display, DefaultScreen(display),
-			KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask );
-
-      /* And change the DDraw parameters */
-      This->d->width	= width;
-      This->d->height	= height;
-    }
-    
-    return DD_OK;
-}
-
-static HRESULT WINAPI DGA2_IDirectDraw2Impl_CreatePalette(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    IDirectDrawPaletteImpl*	ddpal;
-    dga_dp_private		*dppriv;
-    HRESULT			res;
-    int 			xsize = 0,i;
-    DDPRIVATE(This);
-
-    TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,lpddpal,lpunk);
-    res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,(IDirectDrawPaletteImpl**)lpddpal,lpunk,&xsize);
-    if (res != 0)
-	return res;
-    ddpal = *(IDirectDrawPaletteImpl**)lpddpal;
-    ddpal->private = HeapAlloc(
-	GetProcessHeap(),
-	HEAP_ZERO_MEMORY,
-	sizeof(dga_dp_private)
-    );
-    dppriv = (dga_dp_private*)ddpal->private;
-
-    ICOM_VTBL(ddpal)= &dga_ddpalvt;
-    if (This->d->directdraw_pixelformat.u.dwRGBBitCount<=8) {
-	dppriv->cm = TSXDGACreateColormap(display,DefaultScreen(display), ddpriv->dev, AllocAll);
-    } else {
-	ERR("why are we doing CreatePalette in hi/truecolor?\n");
-	dppriv->cm = 0;
-    }
-    if (dppriv->cm && xsize) {
-	for (i=0;i<xsize;i++) {
-	    XColor xc;
-
-	    xc.red = ddpal->palents[i].peRed<<8;
-	    xc.blue = ddpal->palents[i].peBlue<<8;
-	    xc.green = ddpal->palents[i].peGreen<<8;
-	    xc.flags = DoRed|DoBlue|DoGreen;
-	    xc.pixel = i;
-	    TSXStoreColor(display,dppriv->cm,&xc);
+    /* Choose the smallest mode that is large enough. */
+    for (i=0; i < num_modes; i++)
+    {
+	if (modes[i].viewportWidth >= dwWidth && modes[i].viewportHeight >= dwHeight)
+	{
+	    if (best == NULL) best = &modes[i];
+	    else
+	    {
+		if (modes[i].viewportWidth < best->viewportWidth
+		    || modes[i].viewportHeight < best->viewportHeight)
+		    best = &modes[i];
+	    }
 	}
     }
-    return DD_OK;
+
+    /* all modes were too small, use the largest */
+    if (!best)
+    {
+	TRACE("all modes too small\n");
+
+	for (i=1; i < num_modes; i++)
+	{
+	    if (best == NULL) best = &modes[i];
+	    else
+	    {
+		if (modes[i].viewportWidth > best->viewportWidth
+		    || modes[i].viewportHeight > best->viewportHeight)
+		    best = &modes[i];
+	    }
+	}
+    }
+
+    TRACE("using %d %d for %lu %lu\n", best->viewportWidth, best->viewportHeight,
+	  dwWidth, dwHeight);
+
+    return best;
 }
 
-static HRESULT WINAPI DGA2_IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    TRACE("(%p)->()\n",This);
-    Sleep(1000);
-    
-    XDGACloseFramebuffer(display,DefaultScreen(display));
-    XDGASetMode(display,DefaultScreen(display), 0);
+BOOL DDRAW_XF86DGA2_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    if (fdwReason == DLL_PROCESS_ATTACH)
+    {
+	if (initialize())
+	    DDRAW_register_driver(&xf86dga2_driver);
+    }
+    else if (fdwReason == DLL_PROCESS_DETACH)
+    {
+	cleanup();
+    }
+
+    return TRUE;
+}
+
+/* Not called from the vtable. */
+HRESULT XF86DGA2_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
+{
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = User_DirectDraw_Construct(This, ex);
+    if (FAILED(hr)) return hr;
+
+    This->final_release = XF86DGA2_DirectDraw_final_release;
+
+    This->create_primary    = XF86DGA2_DirectDraw_create_primary;
+    This->create_backbuffer = XF86DGA2_DirectDraw_create_backbuffer;
+
+    ICOM_INIT_INTERFACE(This, IDirectDraw7, XF86DGA2_DirectDraw_VTable);
+
+    return S_OK;
+}
+
+/* This function is called from DirectDrawCreate(Ex) on the most-derived
+ * class to start construction.
+ * Not called from the vtable. */
+HRESULT XF86DGA2_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+				   IUnknown* pUnkOuter, BOOL ex)
+{
+    HRESULT hr;
+    IDirectDrawImpl* This;
+
+    TRACE("\n");
+
+    assert(pUnkOuter == NULL);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(IDirectDrawImpl)
+		     + sizeof(XF86DGA2_DirectDrawImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    /* Note that this relation does *not* hold true if the DD object was
+     * CoCreateInstanced then Initialized. */
+    This->private = (XF86DGA2_DirectDrawImpl *)(This+1);
+
+    hr = XF86DGA2_DirectDraw_Construct(This, ex);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*pIface = ICOM_INTERFACE(This, IDirectDraw7);
+
+    return hr;
+}
+
+/* This function is called from Uninit_DirectDraw_Initialize on the
+ * most-derived-class to start initialization.
+ * Not called from the vtable. */
+HRESULT XF86DGA2_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
+{
+    HRESULT hr;
+
+    TRACE("\n");
+
+    This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+			      sizeof(XF86DGA2_DirectDrawImpl));
+    if (This->private == NULL) return E_OUTOFMEMORY;
+
+    hr = XF86DGA2_DirectDraw_Construct(This, TRUE); /* XXX ex? */
+    if (FAILED(hr))
+    {
+	HeapFree(GetProcessHeap(), 0, This->private);
+	return hr;
+    }
 
     return DD_OK;
 }
 
-static ULONG WINAPI DGA2_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDPRIVATE(This);
-    TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
+/* Called from an internal function pointer. */
+void XF86DGA2_DirectDraw_final_release(IDirectDrawImpl *This)
+{
+    XF86DGA2_DDRAW_PRIV_VAR(priv, This);
 
-    if (!--(This->ref)) {
-      if (!--(This->d->ref)) {
-	  TRACE("Closing access to the FrameBuffer\n");
-	  VirtualFree(ddpriv->DGA.fb_addr, 0, MEM_RELEASE);
-	  TSXDGACloseFramebuffer(display, DefaultScreen(display));
-	  TRACE("Going back to normal X mode of operation\n");
-	  TSXDGASetMode(display, DefaultScreen(display), 0);
-
-	  /* Set the input handling back to absolute */
-	  X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
-	  
-	  /* Remove the handling of DGA2 events */
-	  X11DRV_EVENT_SetDGAStatus(0, -1);
-	  
-	  /* Free the modes list */
-	  TSXFree(ddpriv->modes);
-          HeapFree(GetProcessHeap(),0,This->d);
-      }
-      HeapFree(GetProcessHeap(),0,This);
-      return 0;
+    if (priv->xf86dga2.current_mode) {
+	TSXDGASetMode(display, DefaultScreen(display), 0);
+	VirtualFree(priv->xf86dga2.current_mode->data, 0, MEM_RELEASE);
+	X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
+	X11DRV_EVENT_SetDGAStatus(0, -1);
+	TSXFree(priv->xf86dga2.current_mode);
+	TSXDGACloseFramebuffer(display, DefaultScreen(display));
+	priv->xf86dga2.current_mode = NULL;
     }
-    return This->ref;
+
+    User_DirectDraw_final_release(This);
 }
 
-static HRESULT WINAPI DGA2_IDirectDraw2Impl_EnumDisplayModes(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDSURFACEDESC	ddsfd;
-    DDPRIVATE(This);
-    int	i;
-    XDGAMode *modes = ddpriv->modes;
+HRESULT XF86DGA2_DirectDraw_create_primary(IDirectDrawImpl* This,
+					   const DDSURFACEDESC2* pDDSD,
+					   LPDIRECTDRAWSURFACE7* ppSurf,
+					   IUnknown* pUnkOuter)
+{
+    if (This->cooperative_level & DDSCL_EXCLUSIVE)
+	return XF86DGA2_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+    else
+	return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+}
 
-    TRACE("(%p)->(0x%08lx,%p,%p,%p)\n",This,dwFlags,lpddsfd,context,modescb);
-    ddsfd.dwSize = sizeof(ddsfd);
-    ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
-    if (dwFlags & DDEDM_REFRESHRATES) {
-	    ddsfd.dwFlags |= DDSD_REFRESHRATE;
-	    ddsfd.u.dwRefreshRate = 60;
-    }
-    ddsfd.ddsCaps.dwCaps = 0;
-    ddsfd.dwBackBufferCount = 1;
+HRESULT XF86DGA2_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
+					      const DDSURFACEDESC2* pDDSD,
+					      LPDIRECTDRAWSURFACE7* ppSurf,
+					      IUnknown* pUnkOuter,
+					      IDirectDrawSurfaceImpl* primary)
+{
+    if (This->cooperative_level & DDSCL_EXCLUSIVE)
+	return XF86DGA2_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+    else
+	return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+}
 
-
-    ddsfd.dwFlags |= DDSD_PITCH;
-    for (i = 0; i < ddpriv->num_modes; i++) {
-      if (TRACE_ON(ddraw)) {
-	DPRINTF("  Enumerating mode %d : %s (FB: %dx%d / VP: %dx%d) - depth %d -",
-		modes[i].num,
-		modes[i].name, modes[i].imageWidth, modes[i].imageHeight,
-		modes[i].viewportWidth, modes[i].viewportHeight,
-		modes[i].depth);
-	if (modes[i].flags & XDGAConcurrentAccess) DPRINTF(" XDGAConcurrentAccess ");
-	if (modes[i].flags & XDGASolidFillRect) DPRINTF(" XDGASolidFillRect ");
-	if (modes[i].flags & XDGABlitRect) DPRINTF(" XDGABlitRect ");
-	if (modes[i].flags & XDGABlitTransRect) DPRINTF(" XDGABlitTransRect ");
-	if (modes[i].flags & XDGAPixmap) DPRINTF(" XDGAPixmap ");
-	DPRINTF("\n");
-      }
-      /* Fill the pixel format */
-      ddsfd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-      ddsfd.ddpfPixelFormat.dwFourCC = 0;
-      ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
-      ddsfd.ddpfPixelFormat.u.dwRGBBitCount = modes[i].bitsPerPixel;
-      if (modes[i].depth == 8) {
-	ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
-	ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0;
-	ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0;
-	ddsfd.ddpfPixelFormat.u3.dwBBitMask = 0;
-	ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE;
-      } else {
-	ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
-	ddsfd.ddpfPixelFormat.u1.dwRBitMask = modes[i].redMask;
-	ddsfd.ddpfPixelFormat.u2.dwGBitMask = modes[i].greenMask;
-	ddsfd.ddpfPixelFormat.u3.dwBBitMask = modes[i].blueMask;
-      }
-      
-      ddsfd.dwWidth = modes[i].viewportWidth;
-      ddsfd.dwHeight = modes[i].viewportHeight;
-      ddsfd.lPitch = modes[i].imageWidth;
-      
-      /* Send mode to the application */
-      if (!modescb(&ddsfd,context)) return DD_OK;
-    }
-    
+HRESULT WINAPI
+XF86DGA2_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+					LPDDDEVICEIDENTIFIER2 pDDDI,
+					DWORD dwFlags)
+{
+    *pDDDI = xf86dga2_device;
     return DD_OK;
 }
 
-/* Note: Hack so we can reuse the old functions without compiler warnings */
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)	(typeof(dga2_ddvt.fn##fun))
-#else
-# define XCAST(fun)	(void *)
-#endif
-
-struct ICOM_VTABLE(IDirectDraw) dga2_ddvt = 
+HRESULT WINAPI
+XF86DGA2_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
 {
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
-    XCAST(AddRef)IDirectDraw2Impl_AddRef,
-    XCAST(Release)DGA2_IDirectDraw2Impl_Release,
-    XCAST(Compact)IDirectDraw2Impl_Compact,
-    XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
-    XCAST(CreatePalette)DGA2_IDirectDraw2Impl_CreatePalette,
-    XCAST(CreateSurface)DGA2_IDirectDraw2Impl_CreateSurface,
-    XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
-    XCAST(EnumDisplayModes)DGA2_IDirectDraw2Impl_EnumDisplayModes,
-    XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
-    XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
-    XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
-    XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
-    XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
-    XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
-    XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
-    XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
-    XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
-    XCAST(Initialize)IDirectDraw2Impl_Initialize,
-    XCAST(RestoreDisplayMode)DGA2_IDirectDraw2Impl_RestoreDisplayMode,
-    XCAST(SetCooperativeLevel)DGA2_IDirectDraw2Impl_SetCooperativeLevel,
-    DGA2_IDirectDrawImpl_SetDisplayMode,
-    XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
-};
-#undef XCAST
+    ICOM_THIS(IDirectDrawImpl, iface);
+    HRESULT hr;
 
-/*****************************************************************************
- * 	IDirectDraw2
- *
- */
+    TRACE("\n");
 
-static HRESULT WINAPI DGA2_IDirectDraw2Impl_SetDisplayMode(
-    LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD dwRefreshRate, DWORD dwFlags
-) {
-    FIXME( "Ignored parameters (0x%08lx,0x%08lx)\n", dwRefreshRate, dwFlags ); 
-    return DGA2_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
+    hr = Main_DirectDraw_RestoreDisplayMode(iface);
+    if (SUCCEEDED(hr))
+    {
+	XF86DGA2_DDRAW_PRIV_VAR(priv, This);
+
+	if (priv->xf86dga2.current_mode)
+	{
+	    TSXDGASetMode(display, DefaultScreen(display), 0);
+	    VirtualFree(priv->xf86dga2.current_mode->data, 0, MEM_RELEASE);
+	    X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
+	    X11DRV_EVENT_SetDGAStatus(0, -1);
+	    TSXFree(priv->xf86dga2.current_mode);
+	    TSXDGACloseFramebuffer(display, DefaultScreen(display));
+	    priv->xf86dga2.current_mode = NULL;
+	}
+    }
+
+    return hr;
 }
 
-ICOM_VTABLE(IDirectDraw2) dga2_dd2vt = 
+HRESULT WINAPI
+XF86DGA2_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+				   DWORD dwHeight, DWORD dwBPP,
+				   DWORD dwRefreshRate, DWORD dwFlags)
 {
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    DGA_IDirectDraw2Impl_QueryInterface,
-    IDirectDraw2Impl_AddRef,
-    DGA2_IDirectDraw2Impl_Release,
-    IDirectDraw2Impl_Compact,
-    IDirectDraw2Impl_CreateClipper,
-    DGA2_IDirectDraw2Impl_CreatePalette,
-    DGA2_IDirectDraw2Impl_CreateSurface,
-    IDirectDraw2Impl_DuplicateSurface,
-    DGA2_IDirectDraw2Impl_EnumDisplayModes,
-    IDirectDraw2Impl_EnumSurfaces,
-    IDirectDraw2Impl_FlipToGDISurface,
-    DGA_IDirectDraw2Impl_GetCaps,
-    DGA_IDirectDraw2Impl_GetDisplayMode,
-    IDirectDraw2Impl_GetFourCCCodes,
-    IDirectDraw2Impl_GetGDISurface,
-    IDirectDraw2Impl_GetMonitorFrequency,
-    IDirectDraw2Impl_GetScanLine,
-    IDirectDraw2Impl_GetVerticalBlankStatus,
-    IDirectDraw2Impl_Initialize,
-    DGA2_IDirectDraw2Impl_RestoreDisplayMode,
-    DGA2_IDirectDraw2Impl_SetCooperativeLevel,
-    DGA2_IDirectDraw2Impl_SetDisplayMode,
-    IDirectDraw2Impl_WaitForVerticalBlank,
-    DGA_IDirectDraw2Impl_GetAvailableVidMem
+    ICOM_THIS(IDirectDrawImpl, iface);
+
+    HRESULT hr;
+
+    TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
+    hr = User_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP,
+					dwRefreshRate, dwFlags);
+
+    if (SUCCEEDED(hr))
+    {
+	XF86DGA2_DDRAW_PRIV_VAR(priv, This);
+	XDGADevice* old_mode = priv->xf86dga2.current_mode;
+	XDGAMode* new_mode;
+	int old_mode_num = old_mode ? old_mode->mode.num : 0;
+
+	new_mode = choose_mode(dwWidth, dwHeight, dwRefreshRate, dwFlags);
+
+	if (new_mode && new_mode->num != old_mode_num)
+	{
+	    XDGADevice * nm = NULL;
+	    if (old_mode || TSXDGAOpenFramebuffer(display, DefaultScreen(display)))
+		nm = TSXDGASetMode(display, DefaultScreen(display), new_mode->num);
+	    if (nm) {
+		TSXDGASetViewport(display, DefaultScreen(display), 0, 0, XDGAFlipImmediate);
+		if (old_mode) {
+		    VirtualFree(old_mode->data, 0, MEM_RELEASE);
+		    TSXFree(old_mode);
+		} else {
+		    TSXDGASelectInput(display, DefaultScreen(display),
+				      KeyPressMask|KeyReleaseMask|
+				      ButtonPressMask|ButtonReleaseMask|
+				      PointerMotionMask);
+		    X11DRV_EVENT_SetDGAStatus(This->window, dga_event);
+		    X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
+		}
+		priv->xf86dga2.current_mode = nm;
+		priv->xf86dga2.next_vofs = 0;
+		TRACE("frame buffer at %p, pitch=%d, width=%d, height=%d\n", nm->data,
+		      nm->mode.bytesPerScanline, nm->mode.imageWidth, nm->mode.imageHeight);
+		VirtualAlloc(nm->data, nm->mode.bytesPerScanline * nm->mode.imageHeight,
+			     MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
+	    } else {
+		/* argh */
+		ERR("failed\n");
+		/* XXX revert size data to previous mode */
+		if (!old_mode)
+		    TSXDGACloseFramebuffer(display, DefaultScreen(display));
+	    }
+	}
+    }
+
+    return hr;
+}
+
+static ICOM_VTABLE(IDirectDraw7) XF86DGA2_DirectDraw_VTable =
+{
+    Main_DirectDraw_QueryInterface,
+    Main_DirectDraw_AddRef,
+    Main_DirectDraw_Release,
+    Main_DirectDraw_Compact,
+    Main_DirectDraw_CreateClipper,
+    Main_DirectDraw_CreatePalette,
+    Main_DirectDraw_CreateSurface,
+    Main_DirectDraw_DuplicateSurface,
+    User_DirectDraw_EnumDisplayModes,
+    Main_DirectDraw_EnumSurfaces,
+    Main_DirectDraw_FlipToGDISurface,
+    User_DirectDraw_GetCaps,
+    Main_DirectDraw_GetDisplayMode,
+    Main_DirectDraw_GetFourCCCodes,
+    Main_DirectDraw_GetGDISurface,
+    Main_DirectDraw_GetMonitorFrequency,
+    Main_DirectDraw_GetScanLine,
+    Main_DirectDraw_GetVerticalBlankStatus,
+    Main_DirectDraw_Initialize,
+    XF86DGA2_DirectDraw_RestoreDisplayMode,
+    Main_DirectDraw_SetCooperativeLevel,
+    XF86DGA2_DirectDraw_SetDisplayMode,
+    Main_DirectDraw_WaitForVerticalBlank,
+    Main_DirectDraw_GetAvailableVidMem,
+    Main_DirectDraw_GetSurfaceFromDC,
+    Main_DirectDraw_RestoreAllSurfaces,
+    Main_DirectDraw_TestCooperativeLevel,
+    XF86DGA2_DirectDraw_GetDeviceIdentifier,
+    Main_DirectDraw_StartModeTest,
+    Main_DirectDraw_EvaluateMode
 };
 
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)	(typeof(dga2_dd4vt.fn##fun))
-#else
-# define XCAST(fun)	(void*)
-#endif
-
-ICOM_VTABLE(IDirectDraw4) dga2_dd4vt = 
-{
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
-    XCAST(AddRef)IDirectDraw2Impl_AddRef,
-    XCAST(Release)DGA2_IDirectDraw2Impl_Release,
-    XCAST(Compact)IDirectDraw2Impl_Compact,
-    XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
-    XCAST(CreatePalette)DGA2_IDirectDraw2Impl_CreatePalette,
-    XCAST(CreateSurface)DGA2_IDirectDraw2Impl_CreateSurface,
-    XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
-    XCAST(EnumDisplayModes)DGA2_IDirectDraw2Impl_EnumDisplayModes,
-    XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
-    XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
-    XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
-    XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
-    XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
-    XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
-    XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
-    XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
-    XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
-    XCAST(Initialize)IDirectDraw2Impl_Initialize,
-    XCAST(RestoreDisplayMode)DGA2_IDirectDraw2Impl_RestoreDisplayMode,
-    XCAST(SetCooperativeLevel)DGA2_IDirectDraw2Impl_SetCooperativeLevel,
-    XCAST(SetDisplayMode)DGA2_IDirectDrawImpl_SetDisplayMode,
-    XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
-    XCAST(GetAvailableVidMem)DGA_IDirectDraw2Impl_GetAvailableVidMem,
-    IDirectDraw4Impl_GetSurfaceFromDC,
-    IDirectDraw4Impl_RestoreAllSurfaces,
-    IDirectDraw4Impl_TestCooperativeLevel,
-    IDirectDraw4Impl_GetDeviceIdentifier
-};
-#undef XCAST
+#endif  /* HAVE_LIBXXF86DGA2 */
diff --git a/dlls/ddraw/ddraw/dga2.h b/dlls/ddraw/ddraw/dga2.h
new file mode 100644
index 0000000..3dd6b83
--- /dev/null
+++ b/dlls/ddraw/ddraw/dga2.h
@@ -0,0 +1,48 @@
+/* Copyright 2000 TransGaming Technologies, Inc. */
+#ifndef WINE_DDRAW_DDRAW_DGA2_H_INCLUDED
+#define WINE_DDRAW_DDRAW_DGA2_H_INCLUDED
+
+#include <X11/extensions/xf86dga.h>
+
+#define XF86DGA2_DDRAW_PRIV(ddraw) \
+	((XF86DGA2_DirectDrawImpl*)((ddraw)->private))
+#define XF86DGA2_DDRAW_PRIV_VAR(name,ddraw) \
+	XF86DGA2_DirectDrawImpl* name = XF86DGA2_DDRAW_PRIV(ddraw)
+
+typedef struct
+{
+    XDGADevice* current_mode;
+    DWORD next_vofs;
+} XF86DGA2_DirectDrawImpl_Part;
+
+typedef struct
+{
+    User_DirectDrawImpl_Part user;
+    XF86DGA2_DirectDrawImpl_Part xf86dga2;
+} XF86DGA2_DirectDrawImpl;
+
+void XF86DGA2_DirectDraw_final_release(IDirectDrawImpl* This);
+HRESULT XF86DGA2_DirectDraw_create_primary(IDirectDrawImpl* This,
+					   const DDSURFACEDESC2* pDDSD,
+					   LPDIRECTDRAWSURFACE7* ppSurf,
+					   LPUNKNOWN pOuter);
+HRESULT XF86DGA2_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
+					      const DDSURFACEDESC2* pDDSD,
+					      LPDIRECTDRAWSURFACE7* ppSurf,
+					      LPUNKNOWN pOuter,
+					      IDirectDrawSurfaceImpl* primary);
+HRESULT XF86DGA2_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex);
+HRESULT XF86DGA2_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+				   IUnknown* pUnkOuter, BOOL ex);
+HRESULT WINAPI
+XF86DGA2_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+					LPDDDEVICEIDENTIFIER2 pDDDI,
+					DWORD dwFlags);
+HRESULT WINAPI
+XF86DGA2_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+				   DWORD dwHeight, DWORD dwBPP,
+				   DWORD dwRefreshRate, DWORD dwFlags);
+HRESULT WINAPI
+XF86DGA2_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface);
+
+#endif
diff --git a/dlls/ddraw/ddraw/main.c b/dlls/ddraw/ddraw/main.c
index 8becc21..6ef31b9 100644
--- a/dlls/ddraw/ddraw/main.c
+++ b/dlls/ddraw/ddraw/main.c
@@ -2,476 +2,989 @@
  *
  * Copyright 1997-2000 Marcus Meissner
  * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
+ * Copyright 2000 TransGaming Technologies Inc.
  */
 
 /*
  * This file contains all the interface functions that are shared between
- * all interfaces. Or better, it is a "common stub" library for the IDirectDraw*
- * objects
+ * all interfaces. Or better, it is a "common stub" library for the
+ * IDirectDraw* objects
  */
 
 #include "config.h"
 
 #include <assert.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <string.h>
-#include <stdio.h>
 
 #include "winerror.h"
 #include "ddraw.h"
 #include "d3d.h"
 #include "debugtools.h"
 #include "options.h"
+#include "bitmap.h"
+
+#include "ddraw_private.h"
+#include "ddraw/main.h"
+#include "dclipper/main.h"
+#include "dpalette/main.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/fakezbuffer.h"
+#include "dsurface/dibtexture.h"
 
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
-#include "ddraw_private.h"
+extern ICOM_VTABLE(IDirectDraw) DDRAW_IDirectDraw_VTable;
+extern ICOM_VTABLE(IDirectDraw2) DDRAW_IDirectDraw2_VTable;
+extern ICOM_VTABLE(IDirectDraw4) DDRAW_IDirectDraw4_VTable;
 
-HRESULT WINAPI IDirectDraw2Impl_DuplicateSurface(
-    LPDIRECTDRAW2 iface,LPDIRECTDRAWSURFACE src,LPDIRECTDRAWSURFACE *dst
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    FIXME("(%p)->(%p,%p) simply copies\n",This,src,dst);
-    *dst = src; /* FIXME */
+static void DDRAW_UnsubclassWindow(IDirectDrawImpl* This);
+
+static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl* This);
+static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl* This);
+static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl* This);
+static void LosePrimarySurface(IDirectDrawImpl* This);
+
+static const char ddProp[] = "WINE_DDRAW_Property";
+
+/* Not called from the vtable. */
+HRESULT Main_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
+{
+    /* NOTE: The creator must use HEAP_ZERO_MEMORY or equivalent. */
+    This->ref = 1;
+    This->ex = ex;
+
+    This->final_release = Main_DirectDraw_final_release;
+
+    This->create_palette = Main_DirectDrawPalette_Create;
+
+    This->create_offscreen = Main_create_offscreen;
+    This->create_texture   = Main_create_texture;
+    This->create_zbuffer   = Main_create_zbuffer;
+    /* There are no generic versions of create_{primary,backbuffer}. */
+
+    ICOM_INIT_INTERFACE(This, IDirectDraw,  DDRAW_IDirectDraw_VTable);
+    ICOM_INIT_INTERFACE(This, IDirectDraw2, DDRAW_IDirectDraw2_VTable);
+    ICOM_INIT_INTERFACE(This, IDirectDraw4, DDRAW_IDirectDraw4_VTable);
+    /* There is no generic implementation of IDD7 */
+
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_SetCooperativeLevel(
-    LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-
-    FIXME("(%p)->(%08lx,%08lx)\n",This,(DWORD)hwnd,cooplevel);
-    _dump_cooperativelevel(cooplevel);
-    This->d->mainWindow = hwnd;
-    return DD_OK;
-}
-
-/*
- * Small helper to either use the cooperative window or create a new 
- * one (for mouse and keyboard input) and drawing in the Xlib implementation.
- * 
- * Note this just uses USER calls, so it is safe in here.
- */
-void _common_IDirectDrawImpl_SetDisplayMode(IDirectDrawImpl* This) {
-    RECT	rect;
-
-    /* Do destroy only our window */
-    if (This->d->window && GetPropA(This->d->window,ddProp)) {
-	DestroyWindow(This->d->window);
-	This->d->window = 0;
+void Main_DirectDraw_final_release(IDirectDrawImpl* This)
+{
+    if (IsWindow(This->window))
+    {
+	if (GetPropA(This->window, ddProp))
+	    DDRAW_UnsubclassWindow(This);
+	else
+	    FIXME("this shouldn't happen, right?\n");
     }
-    /* Sanity check cooperative window before assigning it to drawing. */
-    if (IsWindow(This->d->mainWindow) &&
-	IsWindowVisible(This->d->mainWindow)
-    ) {
-	GetWindowRect(This->d->mainWindow,&rect);
-	if ((((rect.right-rect.left) >= This->d->width)	&&
-	     ((rect.bottom-rect.top) >= This->d->height))
-	) {
-	    This->d->window = This->d->mainWindow;
-	    /* FIXME: resizing is not windows compatible behaviour, need test */
-	    /* SetWindowPos(This->d->mainWindow,HWND_TOPMOST,0,0,This->d->width,This->d->height,SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOOWNERZORDER); */
-	    This->d->paintable = 1; /* don't wait for WM_PAINT */
-	}
-    }
-    /* ... failed, create new one. */
-    if (!This->d->window) {
-	This->d->window = CreateWindowExA(
-	    0,
-	    "WINE_DirectDraw",
-	    "WINE_DirectDraw",
-	    WS_POPUP,
-	    0,0,
-	    This->d->width,
-	    This->d->height,
-	    0,
-	    0,
-	    0,
-	    NULL
-	);
-	/*Store THIS with the window. We'll use it in the window procedure*/
-	SetPropA(This->d->window,ddProp,(LONG)This);
-	ShowWindow(This->d->window,TRUE);
-	UpdateWindow(This->d->window);
-    }
-    SetFocus(This->d->window);
+
+    Main_DirectDraw_DeleteSurfaces(This);
+    Main_DirectDraw_DeleteClippers(This);
+    Main_DirectDraw_DeletePalettes(This);
 }
 
-HRESULT WINAPI IDirectDrawImpl_SetDisplayMode(
-	LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
-) {
-        ICOM_THIS(IDirectDrawImpl,iface);
+/* There is no Main_DirectDraw_Create. */
 
-	FIXME("(%p)->SetDisplayMode(%ld,%ld,%ld), needs to be implemented for your display adapter!\n",This,width,height,depth);
-	This->d->width	= width;
-	This->d->height	= height;
-	_common_IDirectDrawImpl_SetDisplayMode(This);
-	return DD_OK;
-}
-
-static void fill_caps(LPDDCAPS caps) {
-    /* This function tries to fill the capabilities of Wines DDraw
-     * implementation. Needs to be fixed, though.. */
-    if (caps == NULL)
-	return;
-
-    caps->dwSize = sizeof(*caps);
-    caps->dwCaps = DDCAPS_ALPHA | DDCAPS_BLT | DDCAPS_BLTSTRETCH | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL | DDCAPS_CANBLTSYSMEM |  DDCAPS_COLORKEY | DDCAPS_PALETTE /*| DDCAPS_NOHARDWARE*/;
-    caps->dwCaps2 = DDCAPS2_CERTIFIED | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_WIDESURFACES;
-    caps->dwCKeyCaps = 0xFFFFFFFF; /* Should put real caps here one day... */
-    caps->dwFXCaps = 0;
-    caps->dwFXAlphaCaps = 0;
-    caps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
-    caps->dwSVCaps = 0;
-    caps->dwZBufferBitDepths = DDBD_16;
-    /* I put here 8 Mo so that D3D applications will believe they have enough
-     * memory to put textures in video memory. BTW, is this only frame buffer
-     * memory or also texture memory (for Voodoo boards for example) ?
-     */
-    caps->dwVidMemTotal = 8192 * 1024;
-    caps->dwVidMemFree = 8192 * 1024;
-    /* These are all the supported capabilities of the surfaces */
-    caps->ddsCaps.dwCaps = DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
-    DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
-      /*DDSCAPS_OVERLAY |*/ DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
-	DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_GetCaps(
-    LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
-)  {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    TRACE("(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
-
-    /* Put the same caps for the two capabilities */
-    fill_caps(caps1);
-    fill_caps(caps2);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_CreateClipper(
-    LPDIRECTDRAW2 iface,DWORD x,LPDIRECTDRAWCLIPPER *lpddclip,LPUNKNOWN lpunk
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    IDirectDrawClipperImpl** ilpddclip=(IDirectDrawClipperImpl**)lpddclip;
-    FIXME("(%p)->(%08lx,%p,%p),stub!\n", This,x,ilpddclip,lpunk);
-    *ilpddclip = (IDirectDrawClipperImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipperImpl));
-    (*ilpddclip)->ref = 1;
-    ICOM_VTBL(*ilpddclip) = &ddclipvt;
-    return DD_OK;
-}
-
-HRESULT WINAPI common_IDirectDraw2Impl_CreatePalette(
-    IDirectDraw2Impl* This,DWORD dwFlags,LPPALETTEENTRY palent,
-    IDirectDrawPaletteImpl **lpddpal,LPUNKNOWN lpunk,int *psize
-) {
-    int size = 0;
-	  
-    if (TRACE_ON(ddraw))
-	_dump_paletteformat(dwFlags);
-	
-    *lpddpal = (IDirectDrawPaletteImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawPaletteImpl));
-    if (*lpddpal == NULL) return E_OUTOFMEMORY;
-    (*lpddpal)->ref = 1;
-    (*lpddpal)->ddraw = (IDirectDrawImpl*)This;
-
-    if (dwFlags & DDPCAPS_1BIT)
-	size = 2;
-    else if (dwFlags & DDPCAPS_2BIT)
-	size = 4;
-    else if (dwFlags & DDPCAPS_4BIT)
-	size = 16;
-    else if (dwFlags & DDPCAPS_8BIT)
-	size = 256;
-    else
-	ERR("unhandled palette format\n");
-
-    *psize = size;
-    if (This->d->palette_convert == NULL) {
-	/* No depth conversion - create 8<->8 identity map */
-	int ent;
-	for (ent=0; ent<256; ent++)
-	    (*lpddpal)->screen_palents[ent] = ent;
-    }
-    if (palent) {
-	/* Now, if we are in depth conversion mode, create the screen palette */
-	if (This->d->palette_convert != NULL)	    
-	    This->d->palette_convert(palent,(*lpddpal)->screen_palents,0,size);
-
-	memcpy((*lpddpal)->palents, palent, size * sizeof(PALETTEENTRY));
-    } else if (This->d->palette_convert != NULL) {
-	/* In that case, put all 0xFF */
-	memset((*lpddpal)->screen_palents, 0xFF, 256 * sizeof(int));
-    }
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_CreatePalette(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    IDirectDrawPaletteImpl** ilpddpal=(IDirectDrawPaletteImpl**)lpddpal;
-    int xsize;
-    HRESULT res;
-
-    TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ilpddpal,lpunk);
-    res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,ilpddpal,lpunk,&xsize);
-    if (res != 0) return res;
-    ICOM_VTBL(*ilpddpal) = &ddraw_ddpalvt;
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    TRACE("(%p)->RestoreDisplayMode()\n", This);
-    Sleep(1000);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_WaitForVerticalBlank(
-    LPDIRECTDRAW2 iface,DWORD x,HANDLE h
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    FIXME("(%p)->(flags=0x%08lx,handle=0x%08x)\n",This,x,h);
-    return DD_OK;
-}
-
-ULONG WINAPI IDirectDraw2Impl_AddRef(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
+ULONG WINAPI Main_DirectDraw_AddRef(LPDIRECTDRAW7 iface) {
+    ICOM_THIS(IDirectDrawImpl,iface);
     TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
 
-    return ++(This->ref);
+    return ++This->ref;
 }
 
-ULONG WINAPI IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
+ULONG WINAPI Main_DirectDraw_Release(LPDIRECTDRAW7 iface) {
+    ULONG ref;
+    ICOM_THIS(IDirectDrawImpl,iface);
     TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
 
-    if (!--(This->ref)) {
-	if (!--(This->d->ref)) {
-	    if (This->d->window && GetPropA(This->d->window,ddProp))
-		DestroyWindow(This->d->window);
-	    HeapFree(GetProcessHeap(),0,This->d);
-	}
-	HeapFree(GetProcessHeap(),0,This);
-	return S_OK;
+    ref = --This->ref;
+
+    if (ref == 0)
+    {
+	if (This->final_release != NULL)
+	    This->final_release(This);
+
+	/* We free the private. This is an artifact of the fact that I don't
+	 * have the destructors set up correctly. */
+	if (This->private != (This+1))
+	    HeapFree(GetProcessHeap(), 0, This->private);
+
+	HeapFree(GetProcessHeap(), 0, This);
     }
-    return This->ref;
+
+    return ref;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_QueryInterface(
-    LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
+/* TODO: need to support IDirect3D. */
+HRESULT WINAPI Main_DirectDraw_QueryInterface(
+    LPDIRECTDRAW7 iface,REFIID refiid,LPVOID *obj
 ) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
+    ICOM_THIS(IDirectDrawImpl,iface);
+    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
 
-    if ( IsEqualGUID( &IID_IUnknown, refiid ) ) {
-	*obj = This;
-	IDirectDraw2_AddRef(iface);
-	TRACE("  Creating IUnknown interface (%p)\n", *obj);
-	return S_OK;
+    if ( IsEqualGUID( &IID_IUnknown, refiid )
+	 || IsEqualGUID( &IID_IDirectDraw7, refiid ) )
+    {
+	*obj = ICOM_INTERFACE(This, IDirectDraw7);
     }
-    ERR("(%p)->(%s,%p), must be implemented by display interface!\n",This,debugstr_guid(refiid),obj);
-    return OLE_E_ENUM_NOMORE;
+    else if ( IsEqualGUID( &IID_IDirectDraw, refiid ) )
+    {
+	*obj = ICOM_INTERFACE(This, IDirectDraw);
+    }
+    else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
+    {
+	*obj = ICOM_INTERFACE(This, IDirectDraw2);
+    }
+    else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
+    {
+	*obj = ICOM_INTERFACE(This, IDirectDraw4);
+    }
+#ifdef HAVE_OPENGL
+    else if ( IsEqualGUID( &IID_IDirect3D3, refiid ) )
+    {
+	return create_direct3d3(obj, This);
+    }
+    else if ( IsEqualGUID( &IID_IDirect3D2, refiid ) )
+    {
+	return create_direct3d2(obj, This);
+    }
+    else if ( IsEqualGUID( &IID_IDirect3D, refiid ) )
+    {
+	return create_direct3d(obj, This);
+    }
+#endif
+    else
+    {
+	FIXME("(%p)->(%s,%p): no interface\n",This,debugstr_guid(refiid),obj);
+	return E_NOINTERFACE;
+    }
+
+    IDirectDraw7_AddRef(iface);
+    return S_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_GetVerticalBlankStatus(
-    LPDIRECTDRAW2 iface,BOOL *status
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    TRACE("(%p)->(%p)\n",This,status);
-    *status = TRUE;
+/* MSDN: "not currently implemented". */
+HRESULT WINAPI Main_DirectDraw_Compact(LPDIRECTDRAW7 iface)
+{
+    TRACE("(%p)\n", iface);
+
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_EnumDisplayModes(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,
-    LPDDENUMMODESCALLBACK modescb
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDSURFACEDESC	ddsfd;
-    static struct {
-	int w,h;
-    } modes[5] = { /* some of the usual modes */
-	{512,384},
-	{640,400},
-	{640,480},
-	{800,600},
-	{1024,768},
+HRESULT WINAPI Main_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface,
+					     DWORD dwFlags,
+					     LPDIRECTDRAWCLIPPER *ppClipper,
+					     IUnknown *pUnkOuter)
+{
+    ICOM_THIS(IDirectDrawImpl, iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(0x%lx, %p, %p)\n", iface, dwFlags, ppClipper, pUnkOuter);
+
+    hr = DirectDrawCreateClipper(dwFlags, ppClipper, pUnkOuter);
+    if (FAILED(hr)) return hr;
+
+    /* dwFlags is passed twice, apparently an API wart. */
+    hr = IDirectDrawClipper_Initialize(*ppClipper,
+				       ICOM_INTERFACE(This, IDirectDraw),
+				       dwFlags);
+    if (FAILED(hr))
+    {
+	IDirectDrawClipper_Release(*ppClipper);
+	return hr;
+    }
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags,
+			      LPPALETTEENTRY palent,
+			      LPDIRECTDRAWPALETTE* ppPalette,
+			      LPUNKNOWN pUnknown)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    LPDIRECTDRAWPALETTE pPalette;
+    HRESULT hr;
+
+    TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ppPalette,pUnknown);
+
+    if (ppPalette == NULL) return E_POINTER; /* unchecked */
+    if (pUnknown != NULL) return CLASS_E_NOAGGREGATION; /* unchecked */
+
+    hr = This->create_palette(This, dwFlags, &pPalette, pUnknown);
+    if (FAILED(hr)) return hr;
+
+    hr = IDirectDrawPalette_SetEntries(pPalette, 0, 0,
+				       Main_DirectDrawPalette_Size(dwFlags),
+				       palent);
+    if (FAILED(hr))
+    {
+	IDirectDrawPalette_Release(pPalette);
+	return hr;
+    }
+    else
+    {
+	*ppPalette = pPalette;
+	return DD_OK;
+    }
+}
+
+HRESULT
+Main_create_offscreen(IDirectDrawImpl* This, const DDSURFACEDESC2* pDDSD,
+		      LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter)
+{
+    assert(pOuter == NULL);
+
+    return DIB_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);
+}
+
+HRESULT
+Main_create_texture(IDirectDrawImpl* This, const DDSURFACEDESC2* pDDSD,
+		    LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter,
+		    DWORD dwMipMapLevel)
+{
+    assert(pOuter == NULL);
+
+    return DIBTexture_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);
+}
+
+HRESULT
+Main_create_zbuffer(IDirectDrawImpl* This, const DDSURFACEDESC2* pDDSD,
+		    LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter)
+{
+    assert(pOuter == NULL);
+
+    return FakeZBuffer_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);
+}
+
+/* Does the texture surface described in pDDSD have any smaller mipmaps? */
+static BOOL more_mipmaps(const DDSURFACEDESC2 *pDDSD)
+{
+    return ((pDDSD->dwFlags & DDSD_MIPMAPCOUNT) && pDDSD->u2.dwMipMapCount > 1
+	    && (pDDSD->dwWidth > 1 || pDDSD->dwHeight > 1));
+}
+
+/* Create a texture surface along with any of its mipmaps. */
+static HRESULT
+create_texture(IDirectDrawImpl* This, const DDSURFACEDESC2 *pDDSD,
+	       LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pUnkOuter)
+{
+    DDSURFACEDESC2 ddsd;
+    DWORD mipmap_level = 0;
+    HRESULT hr;
+
+    assert(pUnkOuter == NULL);
+
+    /* is this check right? (pixelformat can be copied from primary) */
+    if ((pDDSD->dwFlags&(DDSD_HEIGHT|DDSD_WIDTH)) != (DDSD_HEIGHT|DDSD_WIDTH))
+	return DDERR_INVALIDPARAMS;
+
+    ddsd = *pDDSD;
+
+    if (!(ddsd.dwFlags & DDSD_PIXELFORMAT))
+    {
+	ddsd.u4.ddpfPixelFormat = This->pixelformat;
+    }
+
+    if (!(ddsd.dwFlags & DDSD_PITCH))
+    {
+	ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth,
+						  GET_BPP(ddsd)*8);
+    }
+
+    ddsd.dwFlags |= DDSD_PITCH | DDSD_PIXELFORMAT;
+
+    hr = This->create_texture(This, &ddsd, ppSurf, pUnkOuter, mipmap_level);
+    if (FAILED(hr)) return hr;
+
+    /* Create attached mipmaps if required. */
+    if (more_mipmaps(&ddsd))
+    {
+	LPDIRECTDRAWSURFACE7 mipmap;
+	LPDIRECTDRAWSURFACE7 prev_mipmap;
+	DDSURFACEDESC2 mipmap_surface_desc;
+
+	prev_mipmap = *ppSurf;
+	IDirectDrawSurface7_AddRef(prev_mipmap);
+	mipmap_surface_desc = ddsd;
+
+	while (more_mipmaps(&mipmap_surface_desc))
+	{
+	    mipmap_level++;
+
+	    mipmap_surface_desc.u2.dwMipMapCount--;
+
+	    if (mipmap_surface_desc.dwWidth > 1)
+		mipmap_surface_desc.dwWidth /= 2;
+
+	    if (mipmap_surface_desc.dwHeight > 1)
+		mipmap_surface_desc.dwHeight /= 2;
+
+	    mipmap_surface_desc.u1.lPitch
+		= DDRAW_width_bpp_to_pitch(mipmap_surface_desc.dwWidth,
+					   GET_BPP(ddsd)*8);
+
+	    hr = This->create_texture(This, &mipmap_surface_desc, &mipmap,
+				      pUnkOuter, mipmap_level);
+	    if (FAILED(hr))
+	    {
+		IDirectDrawSurface7_Release(prev_mipmap);
+		IDirectDrawSurface7_Release(*ppSurf);
+		return hr;
+	    }
+
+	    IDirectDrawSurface7_AddAttachedSurface(prev_mipmap, mipmap);
+	    IDirectDrawSurface7_Release(prev_mipmap);
+	    prev_mipmap = mipmap;
+	}
+
+	IDirectDrawSurface7_Release(prev_mipmap);
+    }
+
+    return DD_OK;
+}
+
+/* Creates a primary surface and any indicated backbuffers. */
+static HRESULT
+create_primary(IDirectDrawImpl* This, LPDDSURFACEDESC2 pDDSD,
+	       LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pUnkOuter)
+{
+    DDSURFACEDESC2 ddsd;
+    HRESULT hr;
+
+    assert(pUnkOuter == NULL);
+
+    if (This->primary_surface != NULL)
+	return DDERR_PRIMARYSURFACEALREADYEXISTS;
+
+    /* as documented (what about pitch?) */
+    if (pDDSD->dwFlags & (DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT))
+	return DDERR_INVALIDPARAMS;
+
+    ddsd = *pDDSD;
+    ddsd.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT;
+    ddsd.dwHeight = This->height;
+    ddsd.dwWidth = This->width;
+    ddsd.u1.lPitch = This->pitch;
+    ddsd.u4.ddpfPixelFormat = This->pixelformat;
+    ddsd.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY
+	| DDSCAPS_VISIBLE | DDSCAPS_FRONTBUFFER;
+
+    if ((ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) && ddsd.dwBackBufferCount > 0)
+	ddsd.ddsCaps.dwCaps |= DDSCAPS_FLIP;
+
+    hr = This->create_primary(This, &ddsd, ppSurf, pUnkOuter);
+    if (FAILED(hr)) return hr;
+
+    if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT)
+    {
+	IDirectDrawSurfaceImpl* primary;
+	LPDIRECTDRAWSURFACE7 pPrev;
+	DWORD i;
+
+	ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+	ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE
+				 | DDSCAPS_BACKBUFFER);
+
+	primary = ICOM_OBJECT(IDirectDrawSurfaceImpl,IDirectDrawSurface7,
+			      *ppSurf);
+	pPrev = *ppSurf;
+	IDirectDrawSurface7_AddRef(pPrev);
+
+	for (i=0; i < ddsd.dwBackBufferCount; i++)
+	{
+	    LPDIRECTDRAWSURFACE7 pBack;
+
+	    if (i == 0)
+		ddsd.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
+	    else
+		ddsd.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
+
+	    hr = This->create_backbuffer(This, &ddsd, &pBack, pUnkOuter,
+					 primary);
+
+	    if (FAILED(hr))
+	    {
+		IDirectDraw7_Release(pPrev);
+		IDirectDraw7_Release(*ppSurf);
+		return hr;
+	    }
+
+	    IDirectDrawSurface7_AddAttachedSurface(pPrev, pBack);
+	    IDirectDrawSurface7_Release(pPrev);
+	    pPrev = pBack;
+	}
+
+	IDirectDrawSurface7_Release(pPrev);
+    }
+
+    This->primary_surface = *ppSurf;
+
+    return DD_OK;
+}
+
+static HRESULT
+create_offscreen(IDirectDrawImpl* This, LPDDSURFACEDESC2 pDDSD,
+		 LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pUnkOuter)
+{
+    DDSURFACEDESC2 ddsd;
+    HRESULT hr;
+
+    /* is this check right? (pixelformat can be copied from primary) */
+    if ((pDDSD->dwFlags&(DDSD_HEIGHT|DDSD_WIDTH)) != (DDSD_HEIGHT|DDSD_WIDTH))
+	return DDERR_INVALIDPARAMS;
+
+    ddsd = *pDDSD;
+
+    if (!(ddsd.dwFlags & DDSD_PIXELFORMAT))
+    {
+	ddsd.u4.ddpfPixelFormat = This->pixelformat;
+    }
+
+    if (!(ddsd.dwFlags & DDSD_PITCH))
+    {
+	ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth,
+						  GET_BPP(ddsd)*8);
+    }
+
+    ddsd.dwFlags |= DDSD_PITCH | DDSD_PIXELFORMAT;
+
+    hr = This->create_offscreen(This, &ddsd, ppSurf, pUnkOuter);
+    if (FAILED(hr)) return hr;
+
+    return hr;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD,
+			      LPDIRECTDRAWSURFACE7 *ppSurf,
+			      IUnknown *pUnkOuter)
+{
+    HRESULT hr;
+    ICOM_THIS(IDirectDrawImpl, iface);
+
+    TRACE("(%p)->(%p,%p,%p)\n",This,pDDSD,ppSurf,pUnkOuter);
+    TRACE("Requested Caps: 0x%x\n", pDDSD->ddsCaps.dwCaps);
+
+    if (pUnkOuter != NULL)
+	return CLASS_E_NOAGGREGATION; /* unchecked */
+
+    if (!(pDDSD->dwFlags & DDSD_CAPS))
+	return DDERR_INVALIDPARAMS; /* unchecked */
+
+    if (ppSurf == NULL)
+	return E_POINTER; /* unchecked */
+
+    if (pDDSD->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+	/* create primary surface & backbuffers */
+	hr = create_primary(This, pDDSD, ppSurf, pUnkOuter);
+    }
+    else if (pDDSD->ddsCaps.dwCaps & DDSCAPS_BACKBUFFER)
+    {
+       /* create backbuffer surface */
+       hr = This->create_backbuffer(This, pDDSD, ppSurf, pUnkOuter, NULL);
+    }
+    else if (pDDSD->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
+    {
+	/* create offscreenplain surface */
+	hr = create_offscreen(This, pDDSD, ppSurf, pUnkOuter);
+    }
+    else if (pDDSD->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
+    {
+	/* create z-buffer */
+	hr = This->create_zbuffer(This, pDDSD, ppSurf, pUnkOuter);
+    }
+    else if (pDDSD->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
+    {
+	/* create texture */
+	hr = create_texture(This, pDDSD, ppSurf, pUnkOuter);
+    }
+    else
+    {
+	/* Otherwise, assume offscreenplain surface */
+	FIXME("App didn't request a valid surface type - assuming offscreenplain\n");
+	hr = create_offscreen(This, pDDSD, ppSurf, pUnkOuter);
+    }
+
+    if (FAILED(hr)) return hr;
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface, LPDIRECTDRAWSURFACE7 src,
+				 LPDIRECTDRAWSURFACE7* dst)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+
+    IDirectDrawSurfaceImpl *pSrc = ICOM_OBJECT(IDirectDrawSurfaceImpl,
+					       IDirectDrawSurface7, src);
+
+    TRACE("(%p)->(%p,%p)\n",This,src,dst);
+
+    return pSrc->duplicate_surface(pSrc, dst);
+}
+
+/* EnumDisplayModes */
+
+BOOL Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
+					 const DDPIXELFORMAT *provided)
+{
+    /* Some flags must be present in both or neither for a match. */
+    static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
+	| DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
+	| DDPF_ZBUFFER | DDPF_STENCILBUFFER;
+
+    if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
+	return FALSE;
+
+    if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
+	return FALSE;
+
+    if (requested->dwFlags & DDPF_FOURCC)
+	if (requested->dwFourCC != provided->dwFourCC)
+	    return FALSE;
+
+    if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
+			      |DDPF_LUMINANCE|DDPF_BUMPDUDV))
+	if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
+	    return FALSE;
+
+    if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
+			      |DDPF_LUMINANCE|DDPF_BUMPDUDV))
+	if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
+	    return FALSE;
+
+    if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
+	if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
+	    return FALSE;
+
+    /* I could be wrong about the bumpmapping. MSDN docs are vague. */
+    if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
+			      |DDPF_BUMPDUDV))
+	if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
+	    return FALSE;
+
+    if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
+	if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
+	    return FALSE;
+
+    return TRUE;
+}
+
+BOOL Main_DirectDraw_DDSD_Match(const DDSURFACEDESC2* requested,
+				const DDSURFACEDESC2* provided)
+{
+    struct compare_info
+    {
+	DWORD flag;
+	ptrdiff_t offset;
+	size_t size;
     };
-    static int depths[4] = {8,16,24,32};
-    int	i,j;
 
-    TRACE("(%p)->(0x%08lx,%p,%p,%p)\n",This,dwFlags,lpddsfd,context,modescb);
-    ddsfd.dwSize = sizeof(ddsfd);
-    ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
-    if (dwFlags & DDEDM_REFRESHRATES) {
-	ddsfd.dwFlags |= DDSD_REFRESHRATE;
-	ddsfd.u.dwRefreshRate = 60;
+#define CMP(FLAG, FIELD)				\
+	{ DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD),	\
+	  sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
+
+    static const struct compare_info compare[] = {
+	CMP(ALPHABITDEPTH, dwAlphaBitDepth),
+	CMP(BACKBUFFERCOUNT, dwBackBufferCount),
+	CMP(CAPS, ddsCaps),
+	CMP(CKDESTBLT, ddckCKDestBlt),
+	CMP(CKDESTOVERLAY, u3.ddckCKDestOverlay),
+	CMP(CKSRCBLT, ddckCKSrcBlt),
+	CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
+	CMP(HEIGHT, dwHeight),
+	CMP(LINEARSIZE, u1.dwLinearSize),
+	CMP(LPSURFACE, lpSurface),
+	CMP(MIPMAPCOUNT, u2.dwMipMapCount),
+	CMP(PITCH, u1.lPitch),
+	/* PIXELFORMAT: manual */
+	CMP(REFRESHRATE, u2.dwRefreshRate),
+	CMP(TEXTURESTAGE, dwTextureStage),
+	CMP(WIDTH, dwWidth),
+	/* ZBUFFERBITDEPTH: "obsolete" */
+    };
+
+#undef CMP
+
+    int i;
+
+    if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
+	return FALSE;
+
+    for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++)
+    {
+	if (requested->dwFlags & compare[i].flag
+	    && memcmp((const char *)provided + compare[i].offset,
+		      (const char *)requested + compare[i].offset,
+		      compare[i].size) != 0)
+	    return FALSE;
     }
-    ddsfd.ddsCaps.dwCaps = 0;
-    ddsfd.dwBackBufferCount = 1;
 
-    for (i=0;i<sizeof(depths)/sizeof(depths[0]);i++) {
-	ddsfd.dwBackBufferCount = 1;
-	ddsfd.ddpfPixelFormat.dwFourCC	= 0;
-	ddsfd.ddpfPixelFormat.dwFlags 	= DDPF_RGB;
-	ddsfd.ddpfPixelFormat.u.dwRGBBitCount	= depths[i];
-	/* FIXME: those masks would have to be set in depth > 8 */
-	if (depths[i]==8) {
-	  ddsfd.ddpfPixelFormat.u1.dwRBitMask  	= 0;
-	  ddsfd.ddpfPixelFormat.u2.dwGBitMask  	= 0;
-	  ddsfd.ddpfPixelFormat.u3.dwBBitMask 	= 0;
-	  ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
-	  ddsfd.ddsCaps.dwCaps=DDSCAPS_PALETTE;
-	  ddsfd.ddpfPixelFormat.dwFlags|=DDPF_PALETTEINDEXED8;
-	} else {
-	  ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
-	  
-	  /* FIXME: We should query those from X itself */
-	  switch (depths[i]) {
-	  case 16:
-	    ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0xF800;
-	    ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x07E0;
-	    ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x001F;
-	    break;
-	  case 24:
-	    ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0x00FF0000;
-	    ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x0000FF00;
-	    ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x000000FF;
-	    break;
-	  case 32:
-	    ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0x00FF0000;
-	    ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x0000FF00;
-	    ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x000000FF;
-	    break;
-	  }
-	}
+    if (requested->dwFlags & DDSD_PIXELFORMAT)
+    {
+	if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat,
+						 &provided->u4.ddpfPixelFormat))
+	    return FALSE;
+    }
 
-	ddsfd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
-	ddsfd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
-	TRACE(" enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
-	if (!modescb(&ddsfd,context)) return DD_OK;
+    return TRUE;
+}
 
-	for (j=0;j<sizeof(modes)/sizeof(modes[0]);j++) {
-	    ddsfd.dwWidth	= modes[j].w;
-	    ddsfd.dwHeight	= modes[j].h;
-	    TRACE(" enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
-	    if (!modescb(&ddsfd,context)) return DD_OK;
-	}
+#define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
+#define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
 
-	if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
-	    /* modeX is not standard VGA */
+/* This should be extended so that it can be used by
+ * IDirectDrawSurface7::EnumAttachedSurfaces. */
+HRESULT
+Main_DirectDraw_EnumExistingSurfaces(IDirectDrawImpl *This, DWORD dwFlags,
+				     LPDDSURFACEDESC2 lpDDSD2, LPVOID context,
+				     LPDDENUMSURFACESCALLBACK7 callback)
+{
+    IDirectDrawSurfaceImpl *surf;
+    BOOL all, nomatch;
 
-	    ddsfd.dwHeight = 200;
-	    ddsfd.dwWidth = 320;
-	    TRACE(" enumerating (320x200x%d)\n",depths[i]);
-	    if (!modescb(&ddsfd,context)) return DD_OK;
+    /* A NULL lpDDSD2 is permitted if we are enumerating all surfaces anyway */
+    if (lpDDSD2 == NULL && !(dwFlags & DDENUMSURFACES_ALL))
+	return DDERR_INVALIDPARAMS;
+
+    all = dwFlags & DDENUMSURFACES_ALL;
+    nomatch = dwFlags & DDENUMSURFACES_NOMATCH;
+
+    for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw)
+    {
+	if (all
+	    || (nomatch != Main_DirectDraw_DDSD_Match(lpDDSD2,
+						      &surf->surface_desc)))
+	{
+	    LPDIRECTDRAWSURFACE7 surface = ICOM_INTERFACE(surf,
+							  IDirectDrawSurface7);
+
+	    /* BOGUS! Violates COM rules, but MSDN says so. */
+	    IDirectDrawSurface7_AddRef(surface);
+
+	    if (callback(surface, &surf->surface_desc, context)
+		== DDENUMRET_CANCEL)
+		break;
 	}
     }
+
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_GetDisplayMode(
-    LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    TRACE("(%p)->GetDisplayMode(%p)\n",This,lpddsfd);
-    lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
-    lpddsfd->dwHeight = This->d->height;
-    lpddsfd->dwWidth = This->d->width;
-    lpddsfd->lPitch =lpddsfd->dwWidth*PFGET_BPP(This->d->directdraw_pixelformat);
-    lpddsfd->dwBackBufferCount = 2;
-    lpddsfd->u.dwRefreshRate = 60;
-    lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
-    lpddsfd->ddpfPixelFormat = This->d->directdraw_pixelformat;
-    if (TRACE_ON(ddraw))
-	_dump_surface_desc(lpddsfd);
+/* I really don't understand how this is supposed to work.
+ * We only consider dwHeight, dwWidth and ddpfPixelFormat.dwFlags. */
+HRESULT
+Main_DirectDraw_EnumCreateableSurfaces(IDirectDrawImpl *This, DWORD dwFlags,
+				       LPDDSURFACEDESC2 lpDDSD2,
+				       LPVOID context,
+				       LPDDENUMSURFACESCALLBACK7 callback)
+{
+    FIXME("This isn't going to work.\n");
+
+    if ((dwFlags & DDENUMSURFACES_MATCHTYPE) != DDENUMSURFACES_MATCH)
+	return DDERR_INVALIDPARAMS;
+
+    /* TODO: implement this.
+     * Does this work before SCL is called?
+     * Does it only consider off-screen surfaces?
+     */
+
+    return E_FAIL;
+}
+
+/* For unsigned x. 0 is not a power of 2. */
+#define IS_POW_2(x) (((x) & ((x) - 1)) == 0)
+
+HRESULT WINAPI
+Main_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags,
+			     LPDDSURFACEDESC2 lpDDSD2, LPVOID context,
+			     LPDDENUMSURFACESCALLBACK7 callback)
+{
+    ICOM_THIS(IDirectDrawImpl, iface);
+    TRACE("(%p)->(0x%lx, %p, %p, %p)\n", iface, dwFlags, lpDDSD2, context,
+	  callback);
+
+    if (callback == NULL)
+	return DDERR_INVALIDPARAMS;
+
+    if (dwFlags & ~(DDENUMSURFACES_SEARCHTYPE|DDENUMSURFACES_MATCHTYPE))
+	return DDERR_INVALIDPARAMS;
+
+    if (!IS_POW_2(dwFlags & DDENUMSURFACES_SEARCHTYPE)
+	|| !IS_POW_2(dwFlags & DDENUMSURFACES_MATCHTYPE))
+	return DDERR_INVALIDPARAMS;
+
+    if (dwFlags & DDENUMSURFACES_DOESEXIST)
+    {
+	return Main_DirectDraw_EnumExistingSurfaces(This, dwFlags, lpDDSD2,
+						    context, callback);
+    }
+    else
+    {
+	return Main_DirectDraw_EnumCreateableSurfaces(This, dwFlags, lpDDSD2,
+						      context, callback);
+    }
+}
+
+HRESULT WINAPI
+Main_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface,DWORD a,DWORD* b)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    FIXME("(%p)->() stub\n", This);
+
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_FlipToGDISurface(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    FIXME("(%p)->()\n",This);
+HRESULT WINAPI
+Main_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    TRACE("(%p)->()\n",This);
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_GetMonitorFrequency(
-    LPDIRECTDRAW2 iface,LPDWORD freq
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
+/* GetCaps */
+/* GetDeviceIdentifier */
+/* GetDIsplayMode */
+
+HRESULT WINAPI
+Main_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
+			       LPDWORD pCodes)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    FIXME("(%p,%p,%p), stub\n",This,pNumCodes,pCodes);
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface,
+			      LPDIRECTDRAWSURFACE7 *lplpGDIDDSSurface)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    TRACE("(%p)->(%p)\n", This, lplpGDIDDSSurface);
+    TRACE("returning primary (%p)\n", This->primary_surface);
+    *lplpGDIDDSSurface = ICOM_INTERFACE(This->primary_surface, IDirectDrawSurface7);
+    if (*lplpGDIDDSSurface)
+	IDirectDrawSurface7_AddRef(*lplpGDIDDSSurface);
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface,LPDWORD freq)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
     FIXME("(%p)->(%p) returns 60 Hz always\n",This,freq);
     *freq = 60*100; /* 60 Hz */
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_GetFourCCCodes(
-    LPDIRECTDRAW2 iface,LPDWORD x,LPDWORD y
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    FIXME("(%p,%p,%p), stub\n",This,x,y);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_EnumSurfaces(
-    LPDIRECTDRAW2 iface,DWORD x,LPDDSURFACEDESC ddsfd,LPVOID context,
-    LPDDENUMSURFACESCALLBACK ddsfcb
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    FIXME("(%p)->(0x%08lx,%p,%p,%p),stub!\n",This,x,ddsfd,context,ddsfcb);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_Compact( LPDIRECTDRAW2 iface ) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    FIXME("(%p)->()\n", This );
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_GetGDISurface(
-    LPDIRECTDRAW2 iface, LPDIRECTDRAWSURFACE *lplpGDIDDSSurface
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    FIXME("(%p)->(%p)\n", This, lplpGDIDDSSurface);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDraw2Impl_GetScanLine(
-    LPDIRECTDRAW2 iface, LPDWORD lpdwScanLine
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
+HRESULT WINAPI
+Main_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD lpdwScanLine)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
     FIXME("(%p)->(%p)\n", This, lpdwScanLine);
 
-    if (lpdwScanLine)
-	*lpdwScanLine = 1;
+    *lpdwScanLine = 1;
+
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_Initialize(LPDIRECTDRAW2 iface, GUID *lpGUID) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    FIXME("(%p)->(%p)\n", This, lpGUID);
+HRESULT WINAPI
+Main_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hdc,
+				 LPDIRECTDRAWSURFACE7 *lpDDS)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    FIXME("(%p)->(%08ld,%p)\n", This, (DWORD) hdc, lpDDS);
+
     return DD_OK;
 }
 
-/*****************************************************************************
- * 	IDirectDraw2
- *
- * We only need to list the changed/new functions.
- */
-HRESULT WINAPI IDirectDraw2Impl_SetDisplayMode(
-    LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,
-    DWORD dwRefreshRate, DWORD dwFlags
-) {
-    FIXME("Ignoring parameters (0x%08lx,0x%08lx)\n", dwRefreshRate, dwFlags ); 
-    return IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
+HRESULT WINAPI
+Main_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, LPBOOL status)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    TRACE("(%p)->(%p)\n",This,status);
+    *status = TRUE;
+    return DD_OK;
 }
 
-HRESULT WINAPI IDirectDraw2Impl_GetAvailableVidMem(
-    LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
+/* If we were not initialised then Uninit_Main_IDirectDraw7_Initialize would
+ * have been called instead. */
+HRESULT WINAPI
+Main_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID lpGuid)
+{
+    TRACE("(%p)->(%s)\n", iface, debugstr_guid(lpGuid));
+
+    return DDERR_ALREADYINITIALIZED;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    IDirectDrawSurfaceImpl* surf;
+
+    TRACE("(%p)->()\n", This);
+
+    for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw)
+	IDirectDrawSurface7_Restore(ICOM_INTERFACE(surf, IDirectDrawSurface7));
+
+    return DD_OK;
+}
+
+static void DDRAW_SubclassWindow(IDirectDrawImpl* This)
+{
+    /* Well we don't actually subclass the window yet. */
+    SetPropA(This->window, ddProp, (LONG)This);
+}
+
+static void DDRAW_UnsubclassWindow(IDirectDrawImpl* This)
+{
+    RemovePropA(This->window, ddProp);
+}
+
+HRESULT WINAPI
+Main_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hwnd,
+				    DWORD cooplevel)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+
+    FIXME("(%p)->(%08lx,%08lx)\n",This,(DWORD)hwnd,cooplevel);
+    DDRAW_dump_cooperativelevel(cooplevel);
+
+    /* Makes realMYST test happy. */
+    if (This->cooperative_level == cooplevel
+	&& This->window == hwnd)
+	return DD_OK;
+
+    if ((This->cooperative_level & DDSCL_EXCLUSIVE) &&
+        (cooplevel & DDSCL_EXCLUSIVE))
+	return DDERR_EXCLUSIVEMODEALREADYSET;
+
+    /* XXX "It cannot be reset while the process has surfaces or palettes
+     * created." Otherwise the window can be changed??? 
+     * 
+     * This appears to be wrong - comment it out for now.
+    if (This->window)
+	return DDERR_HWNDALREADYSET; 
+    */
+
+    if (!(cooplevel & (DDSCL_EXCLUSIVE|DDSCL_NORMAL)))
+	return DDERR_INVALIDPARAMS;
+
+    This->window = hwnd;
+    This->cooperative_level = cooplevel;
+
+    ShowWindow(hwnd, SW_SHOW);
+
+    DDRAW_SubclassWindow(This);
+
+    /* TODO Does it also get resized to the current screen size? */
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+			       DWORD dwHeight, LONG lPitch,
+			       DWORD dwRefreshRate, DWORD dwFlags,
+			       const DDPIXELFORMAT* pixelformat)
+{
+    short screenX;
+    short screenY;
+    
+    ICOM_THIS(IDirectDrawImpl,iface);
+
+    TRACE("(%p)->SetDisplayMode(%ld,%ld)\n",This,dwWidth,dwHeight);
+
+    if (!(This->cooperative_level & DDSCL_EXCLUSIVE))
+	return DDERR_NOEXCLUSIVEMODE;
+
+    if (!IsWindow(This->window))
+	return DDERR_GENERIC; /* unchecked */
+
+    LosePrimarySurface(This);
+
+    screenX = GetSystemMetrics(SM_CXSCREEN);
+    screenY = GetSystemMetrics(SM_CYSCREEN);
+    
+    This->width = dwWidth;
+    This->height = dwHeight;
+    This->pitch = lPitch;
+    This->pixelformat = *pixelformat;
+
+    /* Position the window in the center of the screen - don't center for now */
+    /* MoveWindow(This->window, (screenX-dwWidth)/2, (screenY-dwHeight)/2, 
+                  dwWidth, dwHeight, TRUE);*/
+    MoveWindow(This->window, 0, 0, dwWidth, dwHeight, TRUE);
+
+    SetFocus(This->window);
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+
+    TRACE("(%p)\n",This);
+    if (!(This->cooperative_level & DDSCL_EXCLUSIVE))
+	return DDERR_NOEXCLUSIVEMODE;
+
+    /* Lose the primary surface if the resolution changes. */
+    if (This->orig_width != This->width || This->orig_height != This->height
+	|| This->orig_pitch != This->pitch
+	|| This->orig_pixelformat.dwFlags != This->pixelformat.dwFlags
+	|| !Main_DirectDraw_DDPIXELFORMAT_Match(&This->pixelformat,
+						&This->orig_pixelformat))
+    {
+	LosePrimarySurface(This);
+    }
+
+    /* TODO Move the window back where it belongs. */
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
+				     HANDLE h)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    FIXME("(%p)->(flags=0x%08lx,handle=0x%08x)\n",This,dwFlags,h);
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    TRACE("(%p)->GetDisplayMode(%p)\n",This,pDDSD);
+
+    pDDSD->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_PIXELFORMAT|DDSD_REFRESHRATE;
+    pDDSD->dwHeight = This->height;
+    pDDSD->dwWidth = This->width;
+    pDDSD->u1.lPitch = This->pitch;
+    pDDSD->u2.dwRefreshRate = 60;
+    pDDSD->u4.ddpfPixelFormat = This->pixelformat;
+    pDDSD->ddsCaps.dwCaps = 0;
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 ddscaps,
+				   LPDWORD total, LPDWORD free)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
     TRACE("(%p)->(%p,%p,%p)\n", This,ddscaps,total,free);
 
     /* We have 16 MB videomemory */
@@ -480,122 +993,436 @@
     return DD_OK;
 }
 
-/*****************************************************************************
- * 	IDirectDraw4
- *
+HRESULT WINAPI Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface) {
+    ICOM_THIS(IDirectDrawImpl,iface);
+    TRACE("(%p)->(): stub\n", This);
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pModes,
+			      DWORD dwNumModes, DWORD dwFlags)
+{
+    ICOM_THIS(IDirectDrawImpl,iface);
+    FIXME("(%p)->() stub\n", This);
+
+    return DD_OK;
+}
+
+/*** Owned object management. */
+
+void Main_DirectDraw_AddSurface(IDirectDrawImpl* This,
+				IDirectDrawSurfaceImpl* surface)
+{
+    assert(surface->ddraw_owner == NULL || surface->ddraw_owner == This);
+
+    surface->ddraw_owner = This;
+
+    /* where should it go? */
+    surface->next_ddraw = This->surfaces;
+    surface->prev_ddraw = NULL;
+    if (This->surfaces)
+	This->surfaces->prev_ddraw = surface;
+    This->surfaces = surface;
+}
+
+void Main_DirectDraw_RemoveSurface(IDirectDrawImpl* This,
+				   IDirectDrawSurfaceImpl* surface)
+{
+    assert(surface->ddraw_owner == This);
+
+    if (This->surfaces == surface)
+	This->surfaces = surface->next_ddraw;
+
+    if (This->primary_surface == surface)
+	This->primary_surface = NULL;
+
+    if (surface->next_ddraw)
+	surface->next_ddraw->prev_ddraw = surface->prev_ddraw;
+    if (surface->prev_ddraw)
+	surface->prev_ddraw->next_ddraw = surface->next_ddraw;
+}
+
+static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl* This)
+{
+    while (This->surfaces != NULL)
+	Main_DirectDrawSurface_ForceDestroy(This->surfaces);
+}
+
+void Main_DirectDraw_AddClipper(IDirectDrawImpl* This,
+				IDirectDrawClipperImpl* clipper)
+{
+    assert(clipper->ddraw_owner == NULL || clipper->ddraw_owner == This);
+
+    clipper->ddraw_owner = This;
+
+    clipper->next_ddraw = This->clippers;
+    clipper->prev_ddraw = NULL;
+    if (This->clippers)
+	This->clippers->prev_ddraw = clipper;
+    This->clippers = clipper;
+}
+
+void Main_DirectDraw_RemoveClipper(IDirectDrawImpl* This,
+				   IDirectDrawClipperImpl* clipper)
+{
+    assert(clipper->ddraw_owner == This);
+
+    if (This->clippers == clipper)
+	This->clippers = clipper->next_ddraw;
+
+    if (clipper->next_ddraw)
+	clipper->next_ddraw->prev_ddraw = clipper->prev_ddraw;
+    if (clipper->prev_ddraw)
+	clipper->prev_ddraw->next_ddraw = clipper->next_ddraw;
+}
+
+static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl* This)
+{
+    while (This->clippers != NULL)
+	Main_DirectDrawClipper_ForceDestroy(This->clippers);
+}
+
+void Main_DirectDraw_AddPalette(IDirectDrawImpl* This,
+				IDirectDrawPaletteImpl* palette)
+{
+    assert(palette->ddraw_owner == NULL || palette->ddraw_owner == This);
+
+    palette->ddraw_owner = This;
+
+    /* where should it go? */
+    palette->next_ddraw = This->palettes;
+    palette->prev_ddraw = NULL;
+    if (This->palettes)
+	This->palettes->prev_ddraw = palette;
+    This->palettes = palette;
+}
+
+void Main_DirectDraw_RemovePalette(IDirectDrawImpl* This,
+				   IDirectDrawPaletteImpl* palette)
+{
+    assert(palette->ddraw_owner == This);
+
+    if (This->palettes == palette)
+	This->palettes = palette->next_ddraw;
+
+    if (palette->next_ddraw)
+	palette->next_ddraw->prev_ddraw = palette->prev_ddraw;
+    if (palette->prev_ddraw)
+	palette->prev_ddraw->next_ddraw = palette->next_ddraw;
+}
+
+static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl* This)
+{
+    while (This->palettes != NULL)
+	Main_DirectDrawPalette_ForceDestroy(This->palettes);
+}
+
+/*** ??? */
+
+static void
+LoseSurface(IDirectDrawSurfaceImpl *surface)
+{
+    if (surface != NULL) surface->lose_surface(surface);
+}
+
+static void
+LosePrimarySurface(IDirectDrawImpl *This)
+{
+    /* MSDN: "If another application changes the display mode, the primary
+     * surface is lost, and the method returns DDERR_SURFACELOST until the
+     * primary surface is recreated to match the new display mode."
+     *
+     * We mark all the primary surfaces as lost as soon as the display
+     * mode is changed (by any application). */
+
+    LoseSurface(This->primary_surface);
+}
+
+/******************************************************************************
+ * Uninitialised DirectDraw functions
+ * 
+ * This vtable is used when a DirectDraw object is created with
+ * CoCreateInstance. The only usable method is Initialize.
  */
 
-HRESULT WINAPI IDirectDraw4Impl_GetSurfaceFromDC(
-    LPDIRECTDRAW4 iface, HDC hdc, LPDIRECTDRAWSURFACE *lpDDS
-) {
-    ICOM_THIS(IDirectDraw4Impl,iface);
-    FIXME("(%p)->(%08ld,%p)\n", This, (DWORD) hdc, lpDDS);
-
-    return DD_OK;
+void Uninit_DirectDraw_final_release(IDirectDrawImpl *This)
+{
+    Main_DirectDraw_final_release(This);
 }
 
-HRESULT WINAPI IDirectDraw4Impl_RestoreAllSurfaces(LPDIRECTDRAW4 iface) {
-    ICOM_THIS(IDirectDraw4Impl,iface);
-    FIXME("(%p)->()\n", This);
+static ICOM_VTABLE(IDirectDraw7) Uninit_DirectDraw_VTable;
 
-    return DD_OK;
+/* Not called from the vtable. */
+HRESULT Uninit_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
+{
+    HRESULT hr;
+
+    hr = Main_DirectDraw_Construct(This, ex);
+    if (FAILED(hr)) return hr;
+
+    This->final_release = Uninit_DirectDraw_final_release;
+    ICOM_INIT_INTERFACE(This, IDirectDraw7, Uninit_DirectDraw_VTable);
+
+    return S_OK;
 }
 
-HRESULT WINAPI IDirectDraw4Impl_TestCooperativeLevel(LPDIRECTDRAW4 iface) {
-    ICOM_THIS(IDirectDraw4Impl,iface);
-    FIXME("(%p)->()\n", This);
+HRESULT Uninit_DirectDraw_Create(const GUID* pGUID,
+				       LPDIRECTDRAW7* pIface,
+				       IUnknown* pUnkOuter, BOOL ex)
+{
+    HRESULT hr;
+    IDirectDrawImpl* This;
 
-    return DD_OK;
+    assert(pUnkOuter == NULL); /* XXX no: we must check this */
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(IDirectDrawImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    hr = Uninit_DirectDraw_Construct(This, ex);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, This);
+    else
+	*pIface = ICOM_INTERFACE(This, IDirectDraw7);
+
+    return hr;
 }
 
-HRESULT WINAPI IDirectDraw4Impl_GetDeviceIdentifier(
-    LPDIRECTDRAW4 iface,LPDDDEVICEIDENTIFIER lpdddi,DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDraw4Impl,iface);
-    FIXME("(%p)->(%p,%08lx)\n", This, lpdddi, dwFlags);
+static HRESULT WINAPI
+Uninit_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID pDeviceGuid)
+{
+    const ddraw_driver* driver;
+    ICOM_THIS(IDirectDrawImpl, iface);
 
-    /* just guessing values */
-    strcpy(lpdddi->szDriver,"directdraw");
-    strcpy(lpdddi->szDescription,"WINE DirectDraw");
-    lpdddi->liDriverVersion.s.HighPart = 7;
-    lpdddi->liDriverVersion.s.LowPart = 0;
-    /* Do I smell PCI ids here ? -MM */
-    lpdddi->dwVendorId			= 0;
-    lpdddi->dwDeviceId			= 0;
-    lpdddi->dwSubSysId			= 0;
-    lpdddi->dwRevision			= 1;
-    memset(&(lpdddi->guidDeviceIdentifier),0,sizeof(lpdddi->guidDeviceIdentifier));
-    return DD_OK;
+    TRACE("(%p)->(%p)", iface, pDeviceGuid);
+
+    driver = DDRAW_FindDriver(pDeviceGuid);
+    /* XXX This return value is not documented. (Not checked.) */
+    if (driver == NULL) return DDERR_INVALIDDIRECTDRAWGUID;
+
+    return driver->init(This, pDeviceGuid);
 }
 
-HRESULT WINAPI IDirectDraw7Impl_StartModeTest(
-    LPDIRECTDRAW7 iface,LPSIZE lpModesToTest,DWORD dwNumEntries,DWORD dwFlags
-) {
-    FIXME("(%p)->(%p,%ld,0x%08lx),empty stub!\n",iface,
-	lpModesToTest,dwNumEntries,dwFlags
-    );
-    return DD_OK;
+static HRESULT WINAPI
+Uninit_DirectDraw_Compact(LPDIRECTDRAW7 iface)
+{
+    return DDERR_NOTINITIALIZED;
 }
 
-HRESULT WINAPI IDirectDraw7Impl_EvaluateMode(
-    LPDIRECTDRAW7 iface,DWORD dwFlags, DWORD *pSecondsUntilTimeout
-) {
-    FIXME("(%p)->(0x%08lx,%p),empty stub!\n",iface,
-	dwFlags,pSecondsUntilTimeout
-    );
-    return DD_OK;
+static HRESULT WINAPI
+Uninit_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface, DWORD dwFlags,
+				LPDIRECTDRAWCLIPPER *lplpDDClipper,
+				IUnknown *pUnkOuter)
+
+{
+    return DDERR_NOTINITIALIZED;
 }
 
-HRESULT common_off_screen_CreateSurface(
-    IDirectDraw2Impl* This,IDirectDrawSurfaceImpl* lpdsf
-) {
-    int bpp;
-
-    /* The surface was already allocated when entering in this function */
-    TRACE("using system memory for a surface (%p) \n", lpdsf);
-
-    if (lpdsf->s.surface_desc.dwFlags & DDSD_ZBUFFERBITDEPTH) {
-	/* This is a Z Buffer */
-	TRACE("Creating Z-Buffer of %ld bit depth\n", lpdsf->s.surface_desc.u.dwZBufferBitDepth);
-	bpp = lpdsf->s.surface_desc.u.dwZBufferBitDepth / 8;
-    } else {
-	/* This is a standard image */
-	if (!(lpdsf->s.surface_desc.dwFlags & DDSD_PIXELFORMAT)) {
-	    /* No pixel format => use DirectDraw's format */
-	    lpdsf->s.surface_desc.ddpfPixelFormat = This->d->directdraw_pixelformat;
-	    lpdsf->s.surface_desc.dwFlags |= DDSD_PIXELFORMAT;
-	}
-	bpp = GET_BPP(lpdsf->s.surface_desc);
-
-	/* When the application is requesting a 24 bpp surface and the Direct Draw bpp
-	   is set to 32, we 'upgrade' the requested bpp to 32 to make the blit faster
-	   from off-screen surface to visible surfaces.
-	   
-	   This can also happen with 15 / 16 bpp.
-	   
-	   With this, Windows Media Player works in 32 bpp mode.
-	                  Lionel
-	*/
-	if (((bpp == 3) && (PFGET_BPP(This->d->directdraw_pixelformat) == 4)) ||
-	    ((bpp == 2) && (PFGET_BPP(This->d->directdraw_pixelformat) == 2) &&
-	     (lpdsf->s.surface_desc.ddpfPixelFormat.u1.dwRBitMask != This->d->directdraw_pixelformat.u1.dwRBitMask))) {
-	  TRACE("Warning: 'upgrading' requested pixel format to screen pixel format for blit efficiency\n");
-	  TRACE("         some applications may have problems with it.\n");
-	  bpp = PFGET_BPP(This->d->directdraw_pixelformat);
-	  lpdsf->s.surface_desc.ddpfPixelFormat = This->d->directdraw_pixelformat;
-	}
-    }
-    
-    if (lpdsf->s.surface_desc.dwFlags & DDSD_LPSURFACE)
-	ERR("Creates a surface that is already allocated : assuming this is an application bug !\n");
-
-    lpdsf->s.surface_desc.dwFlags |= DDSD_PITCH|DDSD_LPSURFACE;
-    lpdsf->s.surface_desc.u1.lpSurface =(LPBYTE)VirtualAlloc(
-	NULL,
-	lpdsf->s.surface_desc.dwWidth * lpdsf->s.surface_desc.dwHeight * bpp,
-	MEM_RESERVE | MEM_COMMIT,
-	PAGE_READWRITE
-    );
-    lpdsf->s.surface_desc.lPitch = lpdsf->s.surface_desc.dwWidth * bpp;
-    return DD_OK;
+static HRESULT WINAPI
+Uninit_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags,
+				LPPALETTEENTRY lpColorTable,
+				LPDIRECTDRAWPALETTE *lplpDDPalette,
+				IUnknown *pUnkOuter)
+{
+    return DDERR_NOTINITIALIZED;
 }
+
+static HRESULT WINAPI
+Uninit_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface,
+				LPDDSURFACEDESC2 lpDDSurfaceDesc,
+				LPDIRECTDRAWSURFACE7 *lplpDDSurface,
+				IUnknown *pUnkOuter)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface,
+				   LPDIRECTDRAWSURFACE7 pSurf,
+				   LPDIRECTDRAWSURFACE7 *pDupSurf)
+
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags,
+				   LPDDSURFACEDESC2 lpDDSD,
+				   LPVOID context,
+				   LPDDENUMMODESCALLBACK2 cb)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags,
+			       LPDDSURFACEDESC2 pDDSD, LPVOID context,
+			       LPDDENUMSURFACESCALLBACK7 cb)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
+			  LPDDCAPS pHELCaps)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface,
+				 LPDDSURFACEDESC2 pDDSD)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
+				 LPDWORD pCodes)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface,
+				LPDIRECTDRAWSURFACE7 *pGDISurf)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface, LPDWORD pdwFreq)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD pdwScanLine)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, PBOOL pbIsInVB)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hWnd,
+				      DWORD dwFlags)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+				 DWORD dwHeight, DWORD dwBPP,
+				 DWORD dwRefreshRate, DWORD dwFlags)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
+				       HANDLE hEvent)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 pDDCaps,
+				     LPDWORD pdwTotal, LPDWORD pdwFree)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hDC,
+				   LPDIRECTDRAWSURFACE7 *pSurf)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+				      LPDDDEVICEIDENTIFIER2 pDDDI,
+				      DWORD dwFlags)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pszModes,
+				DWORD cModes, DWORD dwFlags)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI
+Uninit_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface, DWORD dwFlags,
+			       LPDWORD pTimeout)
+{
+    return DDERR_NOTINITIALIZED;
+}
+
+static ICOM_VTABLE(IDirectDraw7) Uninit_DirectDraw_VTable =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    Main_DirectDraw_QueryInterface,
+    Main_DirectDraw_AddRef,
+    Main_DirectDraw_Release,
+    Uninit_DirectDraw_Compact,
+    Uninit_DirectDraw_CreateClipper,
+    Uninit_DirectDraw_CreatePalette,
+    Uninit_DirectDraw_CreateSurface,
+    Uninit_DirectDraw_DuplicateSurface,
+    Uninit_DirectDraw_EnumDisplayModes,
+    Uninit_DirectDraw_EnumSurfaces,
+    Uninit_DirectDraw_FlipToGDISurface,
+    Uninit_DirectDraw_GetCaps,
+    Uninit_DirectDraw_GetDisplayMode,
+    Uninit_DirectDraw_GetFourCCCodes,
+    Uninit_DirectDraw_GetGDISurface,
+    Uninit_DirectDraw_GetMonitorFrequency,
+    Uninit_DirectDraw_GetScanLine,
+    Uninit_DirectDraw_GetVerticalBlankStatus,
+    Uninit_DirectDraw_Initialize,
+    Uninit_DirectDraw_RestoreDisplayMode,
+    Uninit_DirectDraw_SetCooperativeLevel,
+    Uninit_DirectDraw_SetDisplayMode,
+    Uninit_DirectDraw_WaitForVerticalBlank,
+    Uninit_DirectDraw_GetAvailableVidMem,
+    Uninit_DirectDraw_GetSurfaceFromDC,
+    Uninit_DirectDraw_RestoreAllSurfaces,
+    Uninit_DirectDraw_TestCooperativeLevel,
+    Uninit_DirectDraw_GetDeviceIdentifier,
+    Uninit_DirectDraw_StartModeTest,
+    Uninit_DirectDraw_EvaluateMode
+};
diff --git a/dlls/ddraw/ddraw/main.h b/dlls/ddraw/ddraw/main.h
new file mode 100644
index 0000000..1801d11
--- /dev/null
+++ b/dlls/ddraw/ddraw/main.h
@@ -0,0 +1,105 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef WINE_DDRAW_DDRAW_MAIN_H_INCLUDED
+#define WINE_DDRAW_DDRAW_MAIN_H_INCLUDED
+
+/* internal virtual functions */
+void Main_DirectDraw_final_release(IDirectDrawImpl* This);
+HRESULT
+Main_create_offscreen(IDirectDrawImpl* This, const DDSURFACEDESC2 *pDDSD,
+		      LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter);
+HRESULT
+Main_create_texture(IDirectDrawImpl* This, const DDSURFACEDESC2 *pDDSD,
+		    LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter,
+		    DWORD dwMipMapLevel);
+HRESULT
+Main_create_zbuffer(IDirectDrawImpl* This, const DDSURFACEDESC2 *pDDSD,
+		    LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter);
+
+/* internal functions */
+HRESULT Main_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex);
+void Main_DirectDraw_AddSurface(IDirectDrawImpl* This,
+				IDirectDrawSurfaceImpl* surface);
+void Main_DirectDraw_RemoveSurface(IDirectDrawImpl* This,
+				   IDirectDrawSurfaceImpl* surface);
+void Main_DirectDraw_AddClipper(IDirectDrawImpl* This,
+				IDirectDrawClipperImpl* clipper);
+void Main_DirectDraw_RemoveClipper(IDirectDrawImpl* This,
+				   IDirectDrawClipperImpl* clipper);
+void Main_DirectDraw_AddPalette(IDirectDrawImpl* This,
+				IDirectDrawPaletteImpl* surface);
+void Main_DirectDraw_RemovePalette(IDirectDrawImpl* This,
+				   IDirectDrawPaletteImpl* palette);
+
+
+/* interface functions */
+
+ULONG WINAPI Main_DirectDraw_AddRef(LPDIRECTDRAW7 iface);
+ULONG WINAPI Main_DirectDraw_Release(LPDIRECTDRAW7 iface);
+HRESULT WINAPI Main_DirectDraw_QueryInterface(LPDIRECTDRAW7 iface,
+					      REFIID refiid,LPVOID *obj);
+HRESULT WINAPI Main_DirectDraw_Compact(LPDIRECTDRAW7 iface);
+HRESULT WINAPI Main_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface,
+					     DWORD dwFlags,
+					     LPDIRECTDRAWCLIPPER *ppClipper,
+					     IUnknown *pUnkOuter);
+HRESULT WINAPI
+Main_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags,
+			      LPPALETTEENTRY palent,
+			      LPDIRECTDRAWPALETTE* ppPalette,
+			      LPUNKNOWN pUnknown);
+HRESULT WINAPI
+Main_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD,
+			      LPDIRECTDRAWSURFACE7 *ppSurf,
+			      IUnknown *pUnkOuter);
+HRESULT WINAPI
+Main_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface, LPDIRECTDRAWSURFACE7 src,
+				 LPDIRECTDRAWSURFACE7* dst);
+HRESULT WINAPI
+Main_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags,
+			     LPDDSURFACEDESC2 lpDDSD2, LPVOID context,
+			     LPDDENUMSURFACESCALLBACK7 callback);
+HRESULT WINAPI
+Main_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface,DWORD a,DWORD* b);
+HRESULT WINAPI Main_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface);
+HRESULT WINAPI
+Main_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
+			       LPDWORD pCodes);
+HRESULT WINAPI
+Main_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface,
+			      LPDIRECTDRAWSURFACE7 *lplpGDIDDSSurface);
+HRESULT WINAPI
+Main_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface,LPDWORD freq);
+HRESULT WINAPI
+Main_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD lpdwScanLine);
+HRESULT WINAPI
+Main_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hdc,
+				 LPDIRECTDRAWSURFACE7 *lpDDS);
+HRESULT WINAPI
+Main_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, LPBOOL status);
+HRESULT WINAPI
+Main_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID lpGuid);
+HRESULT WINAPI Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface);
+HRESULT WINAPI
+Main_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hwnd,
+				    DWORD cooplevel);
+HRESULT WINAPI
+Main_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+			       DWORD dwHeight, LONG lPitch,
+			       DWORD dwRefreshRate, DWORD dwFlags,
+			       const DDPIXELFORMAT* pixelformat);
+HRESULT WINAPI Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface);
+HRESULT WINAPI
+Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
+				     HANDLE h);
+HRESULT WINAPI
+Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD);
+HRESULT WINAPI
+Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface,LPDDSCAPS2 ddscaps,
+				   LPDWORD total, LPDWORD free);
+HRESULT WINAPI Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface);
+HRESULT WINAPI
+Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pModes,
+			      DWORD dwNumModes, DWORD dwFlags);
+
+#endif
diff --git a/dlls/ddraw/ddraw/thunks.c b/dlls/ddraw/ddraw/thunks.c
new file mode 100644
index 0000000..c76f7a3
--- /dev/null
+++ b/dlls/ddraw/ddraw/thunks.c
@@ -0,0 +1,963 @@
+/* Direct Draw Thunks and old vtables
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+#include <ddraw.h>
+#include "ddraw_private.h"
+#include "ddcomimpl.h"
+
+static HRESULT WINAPI
+IDirectDrawImpl_QueryInterface(LPDIRECTDRAW This, REFIID iid, LPVOID *ppObj)
+{
+    return IDirectDraw7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw,
+							  IDirectDraw7, This),
+				       iid, ppObj);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_QueryInterface(LPDIRECTDRAW2 This, REFIID iid, LPVOID *ppObj)
+{
+    return IDirectDraw7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw2,
+							  IDirectDraw7, This),
+				       iid, ppObj);
+}
+
+
+static HRESULT WINAPI
+IDirectDraw4Impl_QueryInterface(LPDIRECTDRAW4 This, REFIID iid, LPVOID *ppObj)
+{
+    return IDirectDraw7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw4,
+							  IDirectDraw7, This),
+				       iid, ppObj);
+}
+
+static ULONG WINAPI
+IDirectDrawImpl_AddRef(LPDIRECTDRAW This)
+{
+    return IDirectDraw7_AddRef(COM_INTERFACE_CAST(IDirectDrawImpl,
+						  IDirectDraw, IDirectDraw7,
+						  This));
+}
+
+static ULONG WINAPI
+IDirectDraw2Impl_AddRef(LPDIRECTDRAW2 This)
+{
+    return IDirectDraw7_AddRef(COM_INTERFACE_CAST(IDirectDrawImpl,
+						  IDirectDraw2, IDirectDraw7,
+						  This));
+}
+
+static ULONG WINAPI
+IDirectDraw4Impl_AddRef(LPDIRECTDRAW4 This)
+{
+    return IDirectDraw7_AddRef(COM_INTERFACE_CAST(IDirectDrawImpl,
+						  IDirectDraw4, IDirectDraw7,
+						  This));
+}
+
+static ULONG WINAPI
+IDirectDrawImpl_Release(LPDIRECTDRAW This)
+{
+    return IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw, IDirectDraw7,
+						   This));
+}
+
+static ULONG WINAPI
+IDirectDraw2Impl_Release(LPDIRECTDRAW2 This)
+{
+    return IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw2, IDirectDraw7,
+						   This));
+}
+
+static ULONG WINAPI
+IDirectDraw4Impl_Release(LPDIRECTDRAW4 This)
+{
+    return IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw4, IDirectDraw7,
+						   This));
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_Compact(LPDIRECTDRAW This)
+{
+    return IDirectDraw7_Compact(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw, IDirectDraw7,
+						   This));
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_Compact(LPDIRECTDRAW2 This)
+{
+    return IDirectDraw7_Compact(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw2, IDirectDraw7,
+						   This));
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_Compact(LPDIRECTDRAW4 This)
+{
+    return IDirectDraw7_Compact(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw4, IDirectDraw7,
+						   This));
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_CreateClipper(LPDIRECTDRAW This, DWORD dwFlags,
+			      LPDIRECTDRAWCLIPPER *ppClipper,
+			      IUnknown *pUnkOuter)
+{
+    return IDirectDraw7_CreateClipper(COM_INTERFACE_CAST(IDirectDrawImpl,
+							 IDirectDraw,
+							 IDirectDraw7,
+							 This),
+				      dwFlags, ppClipper, pUnkOuter);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_CreateClipper(LPDIRECTDRAW2 This, DWORD dwFlags,
+			       LPDIRECTDRAWCLIPPER *ppClipper,
+			       IUnknown *pUnkOuter)
+{
+    return IDirectDraw7_CreateClipper(COM_INTERFACE_CAST(IDirectDrawImpl,
+							 IDirectDraw2,
+							 IDirectDraw7,
+							 This),
+				      dwFlags, ppClipper, pUnkOuter);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_CreateClipper(LPDIRECTDRAW4 This, DWORD dwFlags,
+			       LPDIRECTDRAWCLIPPER *ppClipper,
+			       IUnknown *pUnkOuter)
+{
+    return IDirectDraw7_CreateClipper(COM_INTERFACE_CAST(IDirectDrawImpl,
+							 IDirectDraw4,
+							 IDirectDraw7,
+							 This),
+				      dwFlags, ppClipper, pUnkOuter);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_CreatePalette(LPDIRECTDRAW This, DWORD dwFlags,
+			      LPPALETTEENTRY pEntries,
+			      LPDIRECTDRAWPALETTE *ppPalette,
+			      IUnknown *pUnkOuter)
+{
+    return IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl,
+							 IDirectDraw,
+							 IDirectDraw7,
+							 This),
+				      dwFlags, pEntries, ppPalette, pUnkOuter);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_CreatePalette(LPDIRECTDRAW2 This, DWORD dwFlags,
+			       LPPALETTEENTRY pEntries,
+			       LPDIRECTDRAWPALETTE *ppPalette,
+			       IUnknown *pUnkOuter)
+{
+    return IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl,
+							 IDirectDraw2,
+							 IDirectDraw7,
+							 This),
+				      dwFlags, pEntries, ppPalette, pUnkOuter);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_CreatePalette(LPDIRECTDRAW4 This, DWORD dwFlags,
+			       LPPALETTEENTRY pEntries,
+			       LPDIRECTDRAWPALETTE *ppPalette,
+			       IUnknown *pUnkOuter)
+{
+    return IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl,
+							 IDirectDraw4,
+							 IDirectDraw7,
+							 This),
+				      dwFlags, pEntries, ppPalette, pUnkOuter);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_CreateSurface(LPDIRECTDRAW This, LPDDSURFACEDESC pSDesc,
+			      LPDIRECTDRAWSURFACE *ppSurface,
+			      IUnknown *pUnkOuter)
+{
+    LPDIRECTDRAWSURFACE7 pSurface7;
+    HRESULT hr;
+
+    hr = IDirectDraw7_CreateSurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+						       IDirectDraw,
+						       IDirectDraw7,
+						       This),
+				    pSDesc, &pSurface7, pUnkOuter);
+
+    *ppSurface = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl,
+				    IDirectDrawSurface7, IDirectDrawSurface3,
+				    pSurface7);
+
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_CreateSurface(LPDIRECTDRAW2 This, LPDDSURFACEDESC pSDesc,
+			       LPDIRECTDRAWSURFACE *ppSurface,
+			       IUnknown *pUnkOuter)
+{
+    LPDIRECTDRAWSURFACE7 pSurface7;
+    HRESULT hr;
+
+    hr = IDirectDraw7_CreateSurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+						       IDirectDraw,
+						       IDirectDraw7,
+						       This),
+				    pSDesc, &pSurface7, pUnkOuter);
+
+    *ppSurface = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl,
+				    IDirectDrawSurface7, IDirectDrawSurface3,
+				    pSurface7);
+
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_CreateSurface(LPDIRECTDRAW4 This, LPDDSURFACEDESC2 pSDesc,
+			       LPDIRECTDRAWSURFACE4 *ppSurface,
+			       IUnknown *pUnkOuter)
+{
+    return IDirectDraw7_CreateSurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							 IDirectDraw4,
+							 IDirectDraw7,
+							 This),
+				      pSDesc,
+				      (LPDIRECTDRAWSURFACE7 *)ppSurface,
+				      pUnkOuter);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_DuplicateSurface(LPDIRECTDRAW This, LPDIRECTDRAWSURFACE pSrc,
+				 LPDIRECTDRAWSURFACE *ppDst)
+{
+    LPDIRECTDRAWSURFACE7 pDst7;
+    HRESULT hr;
+
+    hr = IDirectDraw7_DuplicateSurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw,
+							  IDirectDraw7, This),
+				       COM_INTERFACE_CAST(IDirectDrawSurfaceImpl,
+							  IDirectDrawSurface3,
+							  IDirectDrawSurface7,
+							  pSrc),
+				       &pDst7);
+
+    *ppDst = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
+				IDirectDrawSurface3, pDst7);
+
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_DuplicateSurface(LPDIRECTDRAW2 This, LPDIRECTDRAWSURFACE pSrc,
+				  LPDIRECTDRAWSURFACE *ppDst)
+{
+    LPDIRECTDRAWSURFACE7 pDst7;
+    HRESULT hr;
+
+    hr = IDirectDraw7_DuplicateSurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw2,
+							  IDirectDraw7, This),
+				       COM_INTERFACE_CAST(IDirectDrawSurfaceImpl,
+							  IDirectDrawSurface3,
+							  IDirectDrawSurface7,
+							  pSrc),
+				       &pDst7);
+
+    *ppDst = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
+				IDirectDrawSurface3, pDst7);
+
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_DuplicateSurface(LPDIRECTDRAW4 This,
+				  LPDIRECTDRAWSURFACE4 pSrc,
+				  LPDIRECTDRAWSURFACE4 *ppDst)
+{
+    return IDirectDraw7_DuplicateSurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							    IDirectDraw4,
+							    IDirectDraw7,
+							    This),
+					 (LPDIRECTDRAWSURFACE7)pSrc,
+					 (LPDIRECTDRAWSURFACE7 *)ppDst);
+}
+
+struct displaymodescallback_context
+{
+    LPDDENUMMODESCALLBACK func;
+    LPVOID context;
+};
+
+static HRESULT CALLBACK
+EnumDisplayModesCallbackThunk(LPDDSURFACEDESC2 pDDSD2, LPVOID context)
+{
+    struct displaymodescallback_context *cbcontext = context;
+
+    return cbcontext->func((LPDDSURFACEDESC)pDDSD2, cbcontext->context);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_EnumDisplayModes(LPDIRECTDRAW This, DWORD dwFlags,
+				 LPDDSURFACEDESC pDDSD, LPVOID context,
+				 LPDDENUMMODESCALLBACK cb)
+{
+    struct displaymodescallback_context cbcontext = { cb, context };
+
+    return IDirectDraw7_EnumDisplayModes(COM_INTERFACE_CAST(IDirectDrawImpl,
+							    IDirectDraw,
+							    IDirectDraw7,
+							    This),
+					 dwFlags, pDDSD, &cbcontext,
+					 EnumDisplayModesCallbackThunk);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_EnumDisplayModes(LPDIRECTDRAW2 This, DWORD dwFlags,
+				  LPDDSURFACEDESC pDDSD, LPVOID context,
+				  LPDDENUMMODESCALLBACK cb)
+{
+    struct displaymodescallback_context cbcontext = { cb, context };
+
+    return IDirectDraw7_EnumDisplayModes(COM_INTERFACE_CAST(IDirectDrawImpl,
+							    IDirectDraw2,
+							    IDirectDraw7,
+							    This),
+					 dwFlags, pDDSD, &cbcontext,
+					 EnumDisplayModesCallbackThunk);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_EnumDisplayModes(LPDIRECTDRAW4 This, DWORD dwFlags,
+				  LPDDSURFACEDESC2 pDDSD, LPVOID context,
+				  LPDDENUMMODESCALLBACK2 cb)
+{
+    return IDirectDraw7_EnumDisplayModes(COM_INTERFACE_CAST(IDirectDrawImpl,
+							    IDirectDraw4,
+							    IDirectDraw7,
+							    This),
+					 dwFlags, pDDSD, context, cb);
+}
+
+struct surfacescallback_context
+{
+    LPDDENUMSURFACESCALLBACK func;
+    LPVOID context;
+};
+
+static HRESULT CALLBACK
+EnumSurfacesCallbackThunk(LPDIRECTDRAWSURFACE7 pSurf, LPDDSURFACEDESC2 pDDSD,
+			  LPVOID context)
+{
+    struct surfacescallback_context *cbcontext = context;
+
+    return cbcontext->func(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl,
+					      IDirectDrawSurface7,
+					      IDirectDrawSurface3, pSurf),
+			   (LPDDSURFACEDESC)pDDSD, cbcontext->context);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_EnumSurfaces(LPDIRECTDRAW This, DWORD dwFlags,
+			     LPDDSURFACEDESC pDDSD, LPVOID context,
+			     LPDDENUMSURFACESCALLBACK cb)
+{
+    struct surfacescallback_context cbcontext = { cb, context };
+    return IDirectDraw7_EnumSurfaces(COM_INTERFACE_CAST(IDirectDrawImpl,
+							IDirectDraw,
+							IDirectDraw7, This),
+				     dwFlags, (LPDDSURFACEDESC2)pDDSD,
+				     &cbcontext, EnumSurfacesCallbackThunk);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_EnumSurfaces(LPDIRECTDRAW2 This, DWORD dwFlags,
+			      LPDDSURFACEDESC pDDSD, LPVOID context,
+			      LPDDENUMSURFACESCALLBACK cb)
+{
+    struct surfacescallback_context cbcontext = { cb, context };
+    return IDirectDraw7_EnumSurfaces(COM_INTERFACE_CAST(IDirectDrawImpl,
+							IDirectDraw2,
+							IDirectDraw7, This),
+				     dwFlags, (LPDDSURFACEDESC2)pDDSD,
+				     &cbcontext, EnumSurfacesCallbackThunk);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_EnumSurfaces(LPDIRECTDRAW4 This, DWORD dwFlags,
+			      LPDDSURFACEDESC2 pDDSD, LPVOID context,
+			      LPDDENUMSURFACESCALLBACK2 cb)
+{
+    return IDirectDraw7_EnumSurfaces(COM_INTERFACE_CAST(IDirectDrawImpl,
+							IDirectDraw4,
+							IDirectDraw7, This),
+				     dwFlags, pDDSD, context,
+				     (LPDDENUMSURFACESCALLBACK7)cb);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_FlipToGDISurface(LPDIRECTDRAW This)
+{
+    return IDirectDraw7_FlipToGDISurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							    IDirectDraw,
+							    IDirectDraw7,
+							    This));
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_FlipToGDISurface(LPDIRECTDRAW2 This)
+{
+    return IDirectDraw7_FlipToGDISurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							    IDirectDraw2,
+							    IDirectDraw7,
+							    This));
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_FlipToGDISurface(LPDIRECTDRAW4 This)
+{
+    return IDirectDraw7_FlipToGDISurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							    IDirectDraw4,
+							    IDirectDraw7,
+							    This));
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_GetCaps(LPDIRECTDRAW This, LPDDCAPS pDDC1, LPDDCAPS pDDC2)
+{
+    return IDirectDraw7_GetCaps(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw, IDirectDraw7,
+						   This), pDDC1, pDDC2);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_GetCaps(LPDIRECTDRAW2 This, LPDDCAPS pDDC1, LPDDCAPS pDDC2)
+{
+    return IDirectDraw7_GetCaps(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw2, IDirectDraw7,
+						   This), pDDC1, pDDC2);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetCaps(LPDIRECTDRAW4 This, LPDDCAPS pDDC1, LPDDCAPS pDDC2)
+{
+    return IDirectDraw7_GetCaps(COM_INTERFACE_CAST(IDirectDrawImpl,
+						   IDirectDraw4, IDirectDraw7,
+						   This), pDDC1, pDDC2);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_GetDisplayMode(LPDIRECTDRAW This, LPDDSURFACEDESC pDDSD)
+{
+    return IDirectDraw7_GetDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw,
+							  IDirectDraw7, This),
+				       (LPDDSURFACEDESC2)pDDSD);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_GetDisplayMode(LPDIRECTDRAW2 This, LPDDSURFACEDESC pDDSD)
+{
+    return IDirectDraw7_GetDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw2,
+							  IDirectDraw7, This),
+				       (LPDDSURFACEDESC2)pDDSD);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetDisplayMode(LPDIRECTDRAW4 This, LPDDSURFACEDESC2 pDDSD)
+{
+    return IDirectDraw7_GetDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw4,
+							  IDirectDraw7, This),
+				       pDDSD);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_GetFourCCCodes(LPDIRECTDRAW This, LPDWORD lpNumCodes,
+			       LPDWORD lpCodes)
+{
+    return IDirectDraw7_GetFourCCCodes(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw,
+							  IDirectDraw7,
+							  This),
+				       lpNumCodes, lpCodes);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_GetFourCCCodes(LPDIRECTDRAW2 This, LPDWORD lpNumCodes,
+				LPDWORD lpCodes)
+{
+    return IDirectDraw7_GetFourCCCodes(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw2,
+							  IDirectDraw7,
+							  This),
+				       lpNumCodes, lpCodes);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetFourCCCodes(LPDIRECTDRAW4 This, LPDWORD lpNumCodes,
+				LPDWORD lpCodes)
+{
+    return IDirectDraw7_GetFourCCCodes(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw4,
+							  IDirectDraw7,
+							  This),
+				       lpNumCodes, lpCodes);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_GetGDISurface(LPDIRECTDRAW This, LPDIRECTDRAWSURFACE *ppSurf)
+{
+    LPDIRECTDRAWSURFACE7 pSurf7;
+    HRESULT hr;
+
+    hr = IDirectDraw7_GetGDISurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+						       IDirectDraw,
+						       IDirectDraw7,
+						       This), &pSurf7);
+
+    *ppSurf = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
+				 IDirectDrawSurface3, pSurf7);
+
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_GetGDISurface(LPDIRECTDRAW2 This, LPDIRECTDRAWSURFACE *ppSurf)
+{
+    LPDIRECTDRAWSURFACE7 pSurf7;
+    HRESULT hr;
+
+    hr = IDirectDraw7_GetGDISurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+						       IDirectDraw2,
+						       IDirectDraw7,
+						       This), &pSurf7);
+
+    *ppSurf = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
+				 IDirectDrawSurface3, pSurf7);
+
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetGDISurface(LPDIRECTDRAW4 This,
+			       LPDIRECTDRAWSURFACE4 *ppSurf)
+{
+    return IDirectDraw7_GetGDISurface(COM_INTERFACE_CAST(IDirectDrawImpl,
+							 IDirectDraw4,
+							 IDirectDraw7,
+							 This),
+				      (LPDIRECTDRAWSURFACE7 *)ppSurf);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_GetMonitorFrequency(LPDIRECTDRAW This, LPDWORD pdwFreq)
+{
+    return IDirectDraw7_GetMonitorFrequency(COM_INTERFACE_CAST(IDirectDrawImpl,
+							       IDirectDraw,
+							       IDirectDraw7,
+							       This),
+					    pdwFreq);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_GetMonitorFrequency(LPDIRECTDRAW2 This, LPDWORD pdwFreq)
+{
+    return IDirectDraw7_GetMonitorFrequency(COM_INTERFACE_CAST(IDirectDrawImpl,
+							       IDirectDraw2,
+							       IDirectDraw7,
+							       This),
+					    pdwFreq);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetMonitorFrequency(LPDIRECTDRAW4 This, LPDWORD pdwFreq)
+{
+    return IDirectDraw7_GetMonitorFrequency(COM_INTERFACE_CAST(IDirectDrawImpl,
+							       IDirectDraw4,
+							       IDirectDraw7,
+							       This),
+					    pdwFreq);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_GetScanLine(LPDIRECTDRAW This, LPDWORD pdwLine)
+{
+    return IDirectDraw7_GetScanLine(COM_INTERFACE_CAST(IDirectDrawImpl,
+						       IDirectDraw,
+						       IDirectDraw7,
+						       This), pdwLine);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_GetScanLine(LPDIRECTDRAW2 This, LPDWORD pdwLine)
+{
+    return IDirectDraw7_GetScanLine(COM_INTERFACE_CAST(IDirectDrawImpl,
+						       IDirectDraw2,
+						       IDirectDraw7,
+						       This), pdwLine);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetScanLine(LPDIRECTDRAW4 This, LPDWORD pdwLine)
+{
+    return IDirectDraw7_GetScanLine(COM_INTERFACE_CAST(IDirectDrawImpl,
+						       IDirectDraw4,
+						       IDirectDraw7,
+						       This), pdwLine);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_GetVerticalBlankStatus(LPDIRECTDRAW This, LPBOOL lpbIsInVB)
+{
+    return IDirectDraw7_GetVerticalBlankStatus(COM_INTERFACE_CAST(IDirectDrawImpl,
+								  IDirectDraw,
+								  IDirectDraw7,
+								  This),
+					       lpbIsInVB);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_GetVerticalBlankStatus(LPDIRECTDRAW2 This, LPBOOL lpbIsInVB)
+{
+    return IDirectDraw7_GetVerticalBlankStatus(COM_INTERFACE_CAST(IDirectDrawImpl,
+								  IDirectDraw2,
+								  IDirectDraw7,
+								  This),
+					       lpbIsInVB);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetVerticalBlankStatus(LPDIRECTDRAW4 This, LPBOOL lpbIsInVB)
+{
+    return IDirectDraw7_GetVerticalBlankStatus(COM_INTERFACE_CAST(IDirectDrawImpl,
+								  IDirectDraw4,
+								  IDirectDraw7,
+								  This),
+					       lpbIsInVB);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_Initialize(LPDIRECTDRAW This, LPGUID pGUID)
+{
+    return IDirectDraw7_Initialize(COM_INTERFACE_CAST(IDirectDrawImpl,
+						      IDirectDraw,
+						      IDirectDraw7, This),
+				   pGUID);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_Initialize(LPDIRECTDRAW2 This, LPGUID pGUID)
+{
+    return IDirectDraw7_Initialize(COM_INTERFACE_CAST(IDirectDrawImpl,
+						      IDirectDraw2,
+						      IDirectDraw7, This),
+				   pGUID);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_Initialize(LPDIRECTDRAW4 This, LPGUID pGUID)
+{
+    return IDirectDraw7_Initialize(COM_INTERFACE_CAST(IDirectDrawImpl,
+						      IDirectDraw4,
+						      IDirectDraw7, This),
+				   pGUID);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_RestoreDisplayMode(LPDIRECTDRAW This)
+{
+    return IDirectDraw7_RestoreDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							      IDirectDraw,
+							      IDirectDraw7,
+							      This));
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 This)
+{
+    return IDirectDraw7_RestoreDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							      IDirectDraw2,
+							      IDirectDraw7,
+							      This));
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_RestoreDisplayMode(LPDIRECTDRAW4 This)
+{
+    return IDirectDraw7_RestoreDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							      IDirectDraw4,
+							      IDirectDraw7,
+							      This));
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_SetCooperativeLevel(LPDIRECTDRAW This, HWND hWnd,
+				    DWORD dwFlags)
+{
+    return IDirectDraw7_SetCooperativeLevel(COM_INTERFACE_CAST(IDirectDrawImpl,
+							       IDirectDraw,
+							       IDirectDraw7,
+							       This),
+					    hWnd, dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_SetCooperativeLevel(LPDIRECTDRAW2 This, HWND hWnd,
+				     DWORD dwFlags)
+{
+    return IDirectDraw7_SetCooperativeLevel(COM_INTERFACE_CAST(IDirectDrawImpl,
+							       IDirectDraw2,
+							       IDirectDraw7,
+							       This),
+					    hWnd, dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_SetCooperativeLevel(LPDIRECTDRAW4 This, HWND hWnd,
+				     DWORD dwFlags)
+{
+    return IDirectDraw7_SetCooperativeLevel(COM_INTERFACE_CAST(IDirectDrawImpl,
+							       IDirectDraw4,
+							       IDirectDraw7,
+							       This),
+					    hWnd, dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_SetDisplayMode(LPDIRECTDRAW This, DWORD a, DWORD b, DWORD c)
+{
+    return IDirectDraw7_SetDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw,
+							  IDirectDraw7,
+							  This),
+				       a, b, c, 0, 0);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_SetDisplayMode(LPDIRECTDRAW2 This, DWORD a, DWORD b, DWORD c,
+				DWORD d, DWORD e)
+{
+    return IDirectDraw7_SetDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw2,
+							  IDirectDraw7,
+							  This),
+				       a, b, c, d, e);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_SetDisplayMode(LPDIRECTDRAW4 This, DWORD a, DWORD b, DWORD c,
+				DWORD d, DWORD e)
+{
+    return IDirectDraw7_SetDisplayMode(COM_INTERFACE_CAST(IDirectDrawImpl,
+							  IDirectDraw4,
+							  IDirectDraw7,
+							  This),
+				       a, b, c, d, e);
+}
+
+static HRESULT WINAPI
+IDirectDrawImpl_WaitForVerticalBlank(LPDIRECTDRAW This, DWORD dwFlags,
+				     HANDLE hEvent)
+{
+    return IDirectDraw7_WaitForVerticalBlank(COM_INTERFACE_CAST(IDirectDrawImpl,
+								IDirectDraw,
+								IDirectDraw7,
+								This),
+					     dwFlags, hEvent);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_WaitForVerticalBlank(LPDIRECTDRAW2 This, DWORD dwFlags,
+				      HANDLE hEvent)
+{
+    return IDirectDraw7_WaitForVerticalBlank(COM_INTERFACE_CAST(IDirectDrawImpl,
+								IDirectDraw2,
+								IDirectDraw7,
+								This),
+					     dwFlags, hEvent);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_WaitForVerticalBlank(LPDIRECTDRAW4 This, DWORD dwFlags,
+				      HANDLE hEvent)
+{
+    return IDirectDraw7_WaitForVerticalBlank(COM_INTERFACE_CAST(IDirectDrawImpl,
+								IDirectDraw4,
+								IDirectDraw7,
+								This),
+					     dwFlags, hEvent);
+}
+
+static HRESULT WINAPI
+IDirectDraw2Impl_GetAvailableVidMem(LPDIRECTDRAW2 This, LPDDSCAPS pCaps,
+				    LPDWORD pdwTotal, LPDWORD pdwFree)
+{
+    DDSCAPS2 Caps2;
+    DDRAW_Convert_DDSCAPS_1_To_2(pCaps, &Caps2);
+
+    return IDirectDraw7_GetAvailableVidMem(COM_INTERFACE_CAST(IDirectDrawImpl,
+							      IDirectDraw2,
+							      IDirectDraw7,
+							      This),
+					   &Caps2, pdwTotal, pdwFree);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetAvailableVidMem(LPDIRECTDRAW4 This, LPDDSCAPS2 pCaps,
+				    LPDWORD pdwTotal, LPDWORD pdwFree)
+{
+    return IDirectDraw7_GetAvailableVidMem(COM_INTERFACE_CAST(IDirectDrawImpl,
+							      IDirectDraw2,
+							      IDirectDraw7,
+							      This),
+					   pCaps, pdwTotal, pdwFree);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetSurfaceFromDC(LPDIRECTDRAW4 This, HDC hDC,
+				  LPDIRECTDRAWSURFACE4 *pSurf)
+{
+    return IDirectDraw7_GetSurfaceFromDC(COM_INTERFACE_CAST(IDirectDrawImpl,
+							    IDirectDraw4,
+							    IDirectDraw7,
+							    This),
+					 hDC, (LPDIRECTDRAWSURFACE7 *)pSurf);
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_RestoreAllSurfaces(LPDIRECTDRAW4 This)
+{
+    return IDirectDraw7_RestoreAllSurfaces(COM_INTERFACE_CAST(IDirectDrawImpl,
+							      IDirectDraw4,
+							      IDirectDraw7,
+							      This));
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_TestCooperativeLevel(LPDIRECTDRAW4 This)
+{
+    return IDirectDraw7_TestCooperativeLevel(COM_INTERFACE_CAST(IDirectDrawImpl,
+								IDirectDraw4,
+								IDirectDraw7,
+								This));
+}
+
+static HRESULT WINAPI
+IDirectDraw4Impl_GetDeviceIdentifier(LPDIRECTDRAW4 This,
+				     LPDDDEVICEIDENTIFIER pDDDI, DWORD dwFlags)
+{
+    DDDEVICEIDENTIFIER2 DDDI2;
+    HRESULT hr;
+
+    hr = IDirectDraw7_GetDeviceIdentifier(COM_INTERFACE_CAST(IDirectDrawImpl,
+							     IDirectDraw4,
+							     IDirectDraw7,
+							     This),
+					  &DDDI2, dwFlags);
+
+    DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(pDDDI, &DDDI2);
+
+    return hr;
+}
+
+ICOM_VTABLE(IDirectDraw) DDRAW_IDirectDraw_VTable =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectDrawImpl_QueryInterface,
+    IDirectDrawImpl_AddRef,
+    IDirectDrawImpl_Release,
+    IDirectDrawImpl_Compact,
+    IDirectDrawImpl_CreateClipper,
+    IDirectDrawImpl_CreatePalette,
+    IDirectDrawImpl_CreateSurface,
+    IDirectDrawImpl_DuplicateSurface,
+    IDirectDrawImpl_EnumDisplayModes,
+    IDirectDrawImpl_EnumSurfaces,
+    IDirectDrawImpl_FlipToGDISurface,
+    IDirectDrawImpl_GetCaps,
+    IDirectDrawImpl_GetDisplayMode,
+    IDirectDrawImpl_GetFourCCCodes,
+    IDirectDrawImpl_GetGDISurface,
+    IDirectDrawImpl_GetMonitorFrequency,
+    IDirectDrawImpl_GetScanLine,
+    IDirectDrawImpl_GetVerticalBlankStatus,
+    IDirectDrawImpl_Initialize,
+    IDirectDrawImpl_RestoreDisplayMode,
+    IDirectDrawImpl_SetCooperativeLevel,
+    IDirectDrawImpl_SetDisplayMode,
+    IDirectDrawImpl_WaitForVerticalBlank,
+};
+
+ICOM_VTABLE(IDirectDraw2) DDRAW_IDirectDraw2_VTable =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectDraw2Impl_QueryInterface,
+    IDirectDraw2Impl_AddRef,
+    IDirectDraw2Impl_Release,
+    IDirectDraw2Impl_Compact,
+    IDirectDraw2Impl_CreateClipper,
+    IDirectDraw2Impl_CreatePalette,
+    IDirectDraw2Impl_CreateSurface,
+    IDirectDraw2Impl_DuplicateSurface,
+    IDirectDraw2Impl_EnumDisplayModes,
+    IDirectDraw2Impl_EnumSurfaces,
+    IDirectDraw2Impl_FlipToGDISurface,
+    IDirectDraw2Impl_GetCaps,
+    IDirectDraw2Impl_GetDisplayMode,
+    IDirectDraw2Impl_GetFourCCCodes,
+    IDirectDraw2Impl_GetGDISurface,
+    IDirectDraw2Impl_GetMonitorFrequency,
+    IDirectDraw2Impl_GetScanLine,
+    IDirectDraw2Impl_GetVerticalBlankStatus,
+    IDirectDraw2Impl_Initialize,
+    IDirectDraw2Impl_RestoreDisplayMode,
+    IDirectDraw2Impl_SetCooperativeLevel,
+    IDirectDraw2Impl_SetDisplayMode,
+    IDirectDraw2Impl_WaitForVerticalBlank,
+    IDirectDraw2Impl_GetAvailableVidMem
+};
+
+ICOM_VTABLE(IDirectDraw4) DDRAW_IDirectDraw4_VTable =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectDraw4Impl_QueryInterface,
+    IDirectDraw4Impl_AddRef,
+    IDirectDraw4Impl_Release,
+    IDirectDraw4Impl_Compact,
+    IDirectDraw4Impl_CreateClipper,
+    IDirectDraw4Impl_CreatePalette,
+    IDirectDraw4Impl_CreateSurface,
+    IDirectDraw4Impl_DuplicateSurface,
+    IDirectDraw4Impl_EnumDisplayModes,
+    IDirectDraw4Impl_EnumSurfaces,
+    IDirectDraw4Impl_FlipToGDISurface,
+    IDirectDraw4Impl_GetCaps,
+    IDirectDraw4Impl_GetDisplayMode,
+    IDirectDraw4Impl_GetFourCCCodes,
+    IDirectDraw4Impl_GetGDISurface,
+    IDirectDraw4Impl_GetMonitorFrequency,
+    IDirectDraw4Impl_GetScanLine,
+    IDirectDraw4Impl_GetVerticalBlankStatus,
+    IDirectDraw4Impl_Initialize,
+    IDirectDraw4Impl_RestoreDisplayMode,
+    IDirectDraw4Impl_SetCooperativeLevel,
+    IDirectDraw4Impl_SetDisplayMode,
+    IDirectDraw4Impl_WaitForVerticalBlank,
+    IDirectDraw4Impl_GetAvailableVidMem,
+    IDirectDraw4Impl_GetSurfaceFromDC,
+    IDirectDraw4Impl_RestoreAllSurfaces,
+    IDirectDraw4Impl_TestCooperativeLevel,
+    IDirectDraw4Impl_GetDeviceIdentifier
+};
diff --git a/dlls/ddraw/ddraw/user.c b/dlls/ddraw/ddraw/user.c
new file mode 100644
index 0000000..e8c78fc
--- /dev/null
+++ b/dlls/ddraw/ddraw/user.c
@@ -0,0 +1,540 @@
+/*	DirectDraw driver for User-based primary surfaces
+ *
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+#include "debugtools.h"
+#include <ddraw.h>
+
+#include <assert.h>
+
+#include "ddraw_private.h"
+#include "ddraw/main.h"
+#include "ddraw/user.h"
+#include "dclipper/main.h"
+#include "dpalette/main.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/user.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static ICOM_VTABLE(IDirectDraw7) User_DirectDraw_VTable;
+
+static const DDDEVICEIDENTIFIER2 user_device = 
+{
+    "User Driver",
+    "WINE DirectDraw on User (and GDI)",
+    { { 0x00010001, 0x00010001 } },
+    0, 0, 0, 0,
+    /* fe38440c-8969-4283-bc73-749e7bc3c2eb */
+    {0xfe38440c,0x8969,0x428e, {0x73,0xbc,0x74,0x9e,0x7b,0xc3,0xc2,0xeb}},
+    0
+};
+
+static const DDPIXELFORMAT pixelformats[] = 
+{
+    /* 8bpp paletted */
+    { sizeof(DDPIXELFORMAT), DDPF_RGB|DDPF_PALETTEINDEXED8, 0, { 8 } },
+    /* 15bpp 5/5/5 */
+    { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, { 16 }, { 0x7C00 }, { 0x3E0 },
+      { 0x1F } },
+    /* 16bpp 5/6/5 */
+    { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, { 16 }, { 0xF800 }, { 0x7E0 },
+      { 0x1F } },
+    /* 24bpp 8/8/8 */
+    { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, { 24 }, { 0xFF0000 },
+      { 0x00FF00 }, { 0x0000FF } },
+    /* 32bpp 8/8/8 */
+    { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, { 32 }, { 0xFF0000 },
+      { 0x00FF00 }, { 0x0000FF } }
+};
+
+HRESULT User_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+				     IUnknown* pUnkOuter, BOOL ex);
+HRESULT User_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
+
+static const ddraw_driver user_driver =
+{
+    &user_device,
+    10,
+    User_DirectDraw_Create,
+    User_DirectDraw_Initialize
+};
+
+BOOL DDRAW_User_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    if (fdwReason == DLL_PROCESS_ATTACH)
+	DDRAW_register_driver(&user_driver);
+
+    return TRUE;
+}
+
+/* If you change this function, you probably want to change the enumeration
+ * code in EnumDisplayModes. */
+static BOOL
+IsValidDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP,
+		   DWORD dwRefreshRate, DWORD dwFlags)
+{
+    if (dwWidth > GetSystemMetrics(SM_CXSCREEN)
+	|| dwHeight > GetSystemMetrics(SM_CYSCREEN))
+	return FALSE;
+
+    switch (dwBPP)
+    {
+    case 8:
+    case 15:
+    case 16:
+    case 24:
+    case 32:
+	break;
+
+    default:
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+static const DDPIXELFORMAT* pixelformat_for_depth(DWORD depth)
+{
+    switch (depth)
+    {
+    case  8: return pixelformats + 0;
+    case 15: return pixelformats + 1;
+    case 16: return pixelformats + 2;
+    case 24: return pixelformats + 3;
+    case 32: return pixelformats + 4;
+    default: return NULL;
+    }
+}
+
+/* Not called from the vtable. */
+HRESULT User_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
+{
+    HRESULT hr;
+    DWORD depth;
+    HDC hDC;
+
+    TRACE("(%p,%d)\n",This,ex);
+
+    hr = Main_DirectDraw_Construct(This, ex);
+    if (FAILED(hr)) return hr;
+
+    This->final_release = User_DirectDraw_final_release;
+
+    This->create_primary    = User_DirectDraw_create_primary;
+    This->create_backbuffer = User_DirectDraw_create_backbuffer;
+
+    hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
+    depth = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
+    DeleteDC(hDC);
+
+    This->width       = GetSystemMetrics(SM_CXSCREEN);
+    This->height      = GetSystemMetrics(SM_CYSCREEN);
+    This->pitch       = DDRAW_width_bpp_to_pitch(This->width, depth);
+    This->pixelformat = *pixelformat_for_depth(depth);
+
+    This->orig_width       = This->width;
+    This->orig_height      = This->height;
+    This->orig_pitch       = This->pitch;
+    This->orig_pixelformat = This->pixelformat;
+
+    ICOM_INIT_INTERFACE(This, IDirectDraw7, User_DirectDraw_VTable);
+
+    return S_OK;
+}
+
+/* This function is called from DirectDrawCreate(Ex) on the most-derived
+ * class to start construction.
+ * Not called from the vtable. */
+HRESULT User_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+			       IUnknown* pUnkOuter, BOOL ex)
+{
+    HRESULT hr;
+    IDirectDrawImpl* This;
+
+    assert(pUnkOuter == NULL);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(IDirectDrawImpl) + sizeof(User_DirectDrawImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    /* Note that this relation does *not* hold true if the DD object was
+     * CoCreateInstanced then Initialized. */
+    This->private = (User_DirectDrawImpl *)(This+1);
+
+    hr = User_DirectDraw_Construct(This, ex);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*pIface = ICOM_INTERFACE(This, IDirectDraw7);
+
+    return hr;
+}
+
+/* This function is called from Uninit_DirectDraw_Initialize on the
+ * most-derived-class to start initialization.
+ * Not called from the vtable. */
+HRESULT User_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
+{
+    HRESULT hr;
+    This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+			      sizeof(User_DirectDrawImpl));
+    if (This->private == NULL) return E_OUTOFMEMORY;
+
+    hr = User_DirectDraw_Construct(This, TRUE); /* XXX ex? */
+    if (FAILED(hr))
+    {
+	HeapFree(GetProcessHeap(), 0, This->private);
+	return hr;
+    }
+
+    return DD_OK;
+}
+
+/* Called from an internal function pointer. */
+void User_DirectDraw_final_release(IDirectDrawImpl *This)
+{
+    Main_DirectDraw_final_release(This);
+}
+
+/* Compact: generic */
+/* CreateClipper: generic */
+/* CreatePalette: generic (with callback) */
+/* CreateSurface: generic (with callbacks) */
+
+HRESULT
+User_DirectDraw_create_primary(IDirectDrawImpl* This,
+			       const DDSURFACEDESC2* pDDSD,
+			       LPDIRECTDRAWSURFACE7* ppSurf,
+			       IUnknown* pUnkOuter)
+{
+    return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+}
+
+HRESULT
+User_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
+				  const DDSURFACEDESC2* pDDSD,
+				  LPDIRECTDRAWSURFACE7* ppSurf,
+				  IUnknown* pUnkOuter,
+				  IDirectDrawSurfaceImpl* primary)
+{
+    return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+}
+
+/* DuplicateSurface: generic */
+
+/* Derived from Xlib_IDirectDraw2Impl_EnumDisplayModes.
+ * Very fake: just enumerate some arbitrary modes.
+ *
+ * The screen sizes are plausible-looking screen sizes and will be limited
+ * by (virtual) screen size.
+ *
+ * The depths are whatever DIBsections support on the client side.
+ * Should they be limited by screen depth?
+ */
+HRESULT WINAPI
+User_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags,
+				 LPDDSURFACEDESC2 pDDSD, LPVOID context,
+				 LPDDENUMMODESCALLBACK2 callback)
+{
+    struct mode
+    {
+	int width;
+	int height;
+    };
+
+    static const struct mode modes[] =
+    {
+	{ 512, 384 }, { 640, 400 }, { 640, 480 }, { 800, 600 }, { 1024, 768 },
+	{ 1152, 864 }, { 1280, 1024 }, { 1600, 1200 }
+    };
+
+    static const int num_modes = sizeof(modes)/sizeof(modes[0]);
+
+    static const int num_pixelformats
+	= sizeof(pixelformats)/sizeof(pixelformats[0]);
+
+    DDSURFACEDESC2 callback_sd;
+
+    int max_width, max_height;
+    int i, j;
+
+    TRACE("(%p)->(0x%08lx,%p,%p,%p)\n",iface,dwFlags,pDDSD,context,callback);
+
+    /* Unfortunately this is the virtual screen size, not physical. */
+    max_width = GetSystemMetrics(SM_CXSCREEN);
+    max_height = GetSystemMetrics(SM_CYSCREEN);
+
+    ZeroMemory(&callback_sd, sizeof(callback_sd));
+    callback_sd.dwSize = sizeof(callback_sd);
+
+    callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_CAPS
+	| DDSD_PITCH;
+
+    if (dwFlags & DDEDM_REFRESHRATES)
+	callback_sd.dwFlags |= DDSD_REFRESHRATE;
+
+    callback_sd.u2.dwRefreshRate = 60.0;
+
+    for (i = 0; i < num_modes; i++)
+    {
+	if (modes[i].width > max_width || modes[i].height > max_height)
+	    continue;
+
+	callback_sd.dwHeight = modes[i].height;
+	callback_sd.dwWidth = modes[i].width;
+
+	TRACE("- mode: %ldx%ld\n", callback_sd.dwWidth, callback_sd.dwHeight);
+	for (j = 0; j < num_pixelformats; j++)
+	{
+	    callback_sd.u1.lPitch
+		= DDRAW_width_bpp_to_pitch(modes[i].width,
+					   pixelformats[j].u1.dwRGBBitCount);
+
+	    callback_sd.u4.ddpfPixelFormat = pixelformats[j];
+
+	    callback_sd.ddsCaps.dwCaps = 0;
+	    if (pixelformats[j].dwFlags & DDPF_PALETTEINDEXED8) /* ick */
+		callback_sd.ddsCaps.dwCaps |= DDSCAPS_PALETTE;
+
+	    assert(IsValidDisplayMode(callback_sd.dwWidth,
+				      callback_sd.dwHeight,
+				      callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
+				      0, 0));
+
+	    TRACE(" - %2ld bpp, R=%08lx G=%08lx B=%08lx\n",
+		  callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
+		  callback_sd.u4.ddpfPixelFormat.u2.dwRBitMask,
+		  callback_sd.u4.ddpfPixelFormat.u3.dwGBitMask,
+		  callback_sd.u4.ddpfPixelFormat.u4.dwBBitMask);
+	    if (callback(&callback_sd, context) == DDENUMRET_CANCEL)
+		return DD_OK;
+	}
+    }
+
+    return DD_OK;
+}
+
+/* EnumSurfaces: generic */
+/* FlipToGDISurface: ??? */
+
+HRESULT WINAPI
+User_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
+			LPDDCAPS pHELCaps)
+{
+/* Based on my guesses for what is appropriate with some clues from the
+ * NVidia driver. Not everything is actually implemented yet.
+ * NV has but we don't: Overlays, Video Ports, DDCAPS_READSCANLINE,
+ * DDCAPS2_CERTIFIED (heh), DDSCAPS2_NONLOCALVIDMEM, DDSCAPS2_COPYFOURCC.
+ * It actually has no FX alpha caps.
+ * Oddly, it doesn't list DDPCAPS_PRIMARYSURFACE.
+ * And the HEL caps make little sense.
+ */
+#define BLIT_CAPS (DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL \
+	  | DDCAPS_BLTSTRETCH | DDCAPS_CANBLTSYSMEM | DDCAPS_CANCLIP	  \
+	  | DDCAPS_CANCLIPSTRETCHED | DDCAPS_COLORKEY			  \
+	  | DDCAPS_COLORKEYHWASSIST)
+
+#define CKEY_CAPS (DDCKEYCAPS_DESTBLT | DDCKEYCAPS_SRCBLT)
+
+#define FX_CAPS (DDFXCAPS_BLTALPHA | DDFXCAPS_BLTMIRRORLEFTRIGHT	\
+		| DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTROTATION90	\
+		| DDFXCAPS_BLTSHRINKX | DDFXCAPS_BLTSHRINKXN		\
+		| DDFXCAPS_BLTSHRINKY | DDFXCAPS_BLTSHRINKXN		\
+		| DDFXCAPS_BLTSTRETCHX | DDFXCAPS_BLTSTRETCHXN		\
+		| DDFXCAPS_BLTSTRETCHY | DDFXCAPS_BLTSTRETCHYN)
+
+#if 0
+#define ROPS { SRCCOPY, SRCPAINT, SRCAND, SRCINVERT, SRCERASE, NOTSRCCOPY, \
+	NOTSRCERASE, MERGEPAINT, BLACKNESS, WHITENESS, }
+#else
+#define ROPS { 0, }
+#endif
+
+    static const DDCAPS caps = 
+    { sizeof(DDCAPS),
+      DDCAPS_3D | DDCAPS_GDI | DDCAPS_PALETTE | BLIT_CAPS,
+      DDCAPS2_CANMANAGETEXTURE | DDCAPS2_CANRENDERWINDOWED | DDCAPS2_CERTIFIED
+      | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_PRIMARYGAMMA
+      | DDCAPS2_WIDESURFACES,
+      CKEY_CAPS,
+      FX_CAPS,
+      0, /* dwFXAlphaCaps */
+      DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE,
+      0, /* dwSVCaps */
+      0, /* ? dwAlphaBitConstBitDepths */
+      0, /* ? dwAlphaBitPixelPitDepths */
+      0, /* ? dwAlphaBltSurfaceBitDepths */
+      0, /* ? dwAlphaOverlayConstBitDepths */
+      0, /* ? dwAlphaOverlayPixelBitDepths */
+      0, /* ? dwAlphaOverlaySurfaceBitDepths */
+      DDBD_16, /* ? dwZBufferBitDepths */
+      16*1024*1024, /* dwVidMemTotal */
+      16*1024*1024, /* dwVidMemFree */
+      0, /* dwMaxVisibleOverlays */
+      0, /* dwCurrVisibleOverlays */
+      0, /* dwNumFourCCCodes */
+      0, /* dwAlignBoundarySrc */
+      0, /* dwAlignSizeSrc */
+      0, /* dwAlignBoundaryDest */
+      0, /* dwAlignSizeDest */
+      0, /* dwAlignStrideAlign */
+      ROPS, /* XXX dwRops[DD_ROP_SPACE] */
+      { 0, }, /* XXX ddsOldCaps */
+      1000, /* dwMinOverlayStretch */
+      1000, /* dwMaxOverlayStretch */
+      1000, /* dwMinLiveVideoStretch */
+      1000, /* dwMaxLiveVideoStretch */
+      1000, /* dwMinHwCodecStretch */
+      1000, /* dwMaxHwCodecStretch */
+      0, 0, 0, /* dwReserved1, 2, 3 */
+      BLIT_CAPS, /* dwSVBCaps */
+      CKEY_CAPS, /* dwSVBCKeyCaps */
+      FX_CAPS, /* dwSVBFXCaps */
+      ROPS, /* dwSVBRops */
+      BLIT_CAPS, /* dwVSBCaps */
+      CKEY_CAPS, /* dwVSBCKeyCaps */
+      FX_CAPS, /* dwVSBFXCaps */
+      ROPS, /* dwVSBRops */
+      BLIT_CAPS, /* dwSSBCaps */
+      CKEY_CAPS, /* dwSSBCKeyCaps */
+      FX_CAPS, /* dwSSBFXCaps */
+      ROPS, /* dwSSBRops */
+      0, /* dwMaxVideoPorts */
+      0, /* dwCurrVideoPorts */
+      0, /* ? dwSVBCaps2 */
+      BLIT_CAPS, /* ? dwNLVBCaps */
+      0, /* ? dwNLVBCaps2 */
+      CKEY_CAPS, /* dwNLVBCKeyCaps */
+      FX_CAPS, /* dwNLVBFXCaps */
+      ROPS, /* dwNLVBRops */
+      { /* ddsCaps */
+	  DDSCAPS_3DDEVICE | DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_FLIP
+	  | DDSCAPS_FRONTBUFFER | DDSCAPS_MIPMAP | DDSCAPS_OFFSCREENPLAIN
+	  | DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY
+	  | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE
+	  | DDSCAPS_ZBUFFER,
+	  DDSCAPS2_CUBEMAP,
+	  0,
+	  0
+      }
+    };
+
+#undef BLIT_CAPS
+#undef CKEY_CAPS
+#undef FX_CAPS
+#undef ROPS
+
+    ICOM_THIS(IDirectDrawImpl, iface);
+	
+    TRACE("(%p)->(%p,%p)\n",This,pDriverCaps,pHELCaps);
+    if ((pDriverCaps != NULL && pDriverCaps->dwSize != sizeof(DDCAPS))
+	|| (pHELCaps != NULL && pHELCaps->dwSize != sizeof(DDCAPS)))
+    {
+	FIXME("unsupported structure versions: %lu/%lu vs %u\n",
+	      pDriverCaps ? pDriverCaps->dwSize : sizeof(DDCAPS),
+	      pHELCaps ? pHELCaps->dwSize : sizeof(DDCAPS),
+	      sizeof(DDCAPS));
+	/* The old DD caps structures are contained in the DX7 SDK, and since
+	 * it's changed every version, we should probably try to support the
+	 * old ones. */
+    }
+
+    if (pDriverCaps != NULL)
+	memcpy(pDriverCaps, &caps, pDriverCaps->dwSize);
+
+    if (pHELCaps != NULL)
+	memcpy(pHELCaps, &caps, pHELCaps->dwSize);
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+User_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+				    LPDDDEVICEIDENTIFIER2 pDDDI,
+				    DWORD dwFlags)
+{
+    TRACE("(%p)->(%p,%08lx)\n",iface,pDDDI,dwFlags);
+    *pDDDI = user_device;
+    return DD_OK;
+}
+
+/* GetDisplayMode: generic */
+/* GetFourCCCodes: generic */
+/* GetGDISurface: ??? */
+/* GetMonitorFrequency: generic */
+/* GetScanLine: generic */
+/* GetSurfaceFromDC: generic */
+/* GetVerticalBlankStatus: generic */
+/* Initialize: generic */
+/* RestoreAllSurfaces: generic */
+/* RestoreDisplayMode: generic */
+/* SetCooperativeLevel: ??? */
+
+HRESULT WINAPI
+User_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+			       DWORD dwHeight, DWORD dwBPP,
+			       DWORD dwRefreshRate, DWORD dwFlags)
+{
+    ICOM_THIS(IDirectDrawImpl, iface);
+
+    const DDPIXELFORMAT* pixelformat;
+    LONG pitch;
+
+    TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
+    if (!IsValidDisplayMode(dwWidth, dwHeight, dwBPP, dwRefreshRate, dwFlags))
+	return DDERR_INVALIDMODE;
+
+    pixelformat = pixelformat_for_depth(dwBPP);
+    if (pixelformat == NULL)
+    {
+	assert(0);
+	return DDERR_GENERIC;
+    }
+
+    pitch = DDRAW_width_bpp_to_pitch(dwWidth, dwBPP);
+
+    return Main_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, pitch,
+					  dwRefreshRate, dwFlags, pixelformat);
+}
+
+/* StartModeTest: ??? */
+/* TestCooperativeLevel: generic? */
+/* WaitForVerticalBlank: ??? */
+
+static ICOM_VTABLE(IDirectDraw7) User_DirectDraw_VTable =
+{
+    Main_DirectDraw_QueryInterface,
+    Main_DirectDraw_AddRef,
+    Main_DirectDraw_Release,
+    Main_DirectDraw_Compact,
+    Main_DirectDraw_CreateClipper,
+    Main_DirectDraw_CreatePalette,
+    Main_DirectDraw_CreateSurface,
+    Main_DirectDraw_DuplicateSurface,
+    User_DirectDraw_EnumDisplayModes,
+    Main_DirectDraw_EnumSurfaces,
+    Main_DirectDraw_FlipToGDISurface,
+    User_DirectDraw_GetCaps,
+    Main_DirectDraw_GetDisplayMode,
+    Main_DirectDraw_GetFourCCCodes,
+    Main_DirectDraw_GetGDISurface,
+    Main_DirectDraw_GetMonitorFrequency,
+    Main_DirectDraw_GetScanLine,
+    Main_DirectDraw_GetVerticalBlankStatus,
+    Main_DirectDraw_Initialize,
+    Main_DirectDraw_RestoreDisplayMode,
+    Main_DirectDraw_SetCooperativeLevel,
+    User_DirectDraw_SetDisplayMode,
+    Main_DirectDraw_WaitForVerticalBlank,
+    Main_DirectDraw_GetAvailableVidMem,
+    Main_DirectDraw_GetSurfaceFromDC,
+    Main_DirectDraw_RestoreAllSurfaces,
+    Main_DirectDraw_TestCooperativeLevel,
+    User_DirectDraw_GetDeviceIdentifier,
+    Main_DirectDraw_StartModeTest,
+    Main_DirectDraw_EvaluateMode
+};
diff --git a/dlls/ddraw/ddraw/user.h b/dlls/ddraw/ddraw/user.h
new file mode 100644
index 0000000..ff15a64
--- /dev/null
+++ b/dlls/ddraw/ddraw/user.h
@@ -0,0 +1,50 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef WINE_DDRAW_DDRAW_USER_H_INCLUDED
+#define WINE_DDRAW_DDRAW_USER_H_INCLUDED
+
+#define USER_DDRAW_PRIV(ddraw) ((User_DirectDrawImpl*)((ddraw)->private))
+#define USER_DDRAW_PRIV_VAR(name,ddraw) \
+	User_DirectDrawImpl* name = USER_DDRAW_PRIV(ddraw)
+
+typedef struct
+{
+    /* empty */
+} User_DirectDrawImpl_Part;
+
+typedef struct
+{
+    User_DirectDrawImpl_Part user;
+} User_DirectDrawImpl;
+
+void User_DirectDraw_final_release(IDirectDrawImpl* This);
+HRESULT User_DirectDraw_create_primary(IDirectDrawImpl* This,
+				       const DDSURFACEDESC2* pDDSD,
+				       LPDIRECTDRAWSURFACE7* ppSurf,
+				       LPUNKNOWN pOuter);
+HRESULT User_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
+					  const DDSURFACEDESC2* pDDSD,
+					  LPDIRECTDRAWSURFACE7* ppSurf,
+					  LPUNKNOWN pOuter,
+					  IDirectDrawSurfaceImpl* primary);
+HRESULT User_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex);
+HRESULT User_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+			       IUnknown* pUnkOuter, BOOL ex);
+
+HRESULT WINAPI
+User_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags,
+				 LPDDSURFACEDESC2 pDDSD, LPVOID context,
+				 LPDDENUMMODESCALLBACK2 callback);
+HRESULT WINAPI
+User_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
+			LPDDCAPS pHELCaps);
+HRESULT WINAPI
+User_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+				    LPDDDEVICEIDENTIFIER2 pDDDI,
+				    DWORD dwFlags);
+HRESULT WINAPI
+User_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+			       DWORD dwHeight, DWORD dwBPP,
+			       DWORD dwRefreshRate, DWORD dwFlags);
+
+#endif
diff --git a/dlls/ddraw/ddraw/x11.c b/dlls/ddraw/ddraw/x11.c
deleted file mode 100644
index b827e81..0000000
--- a/dlls/ddraw/ddraw/x11.c
+++ /dev/null
@@ -1,1335 +0,0 @@
-/*		DirectDraw IDirectDraw Xlib interface
- *
- * Copyright 1997-2000 Marcus Meissner
- * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
- */
-/*
- * This file contains the Xlib specific interface functions.
- */
-
-#include "config.h"
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "winerror.h"
-#include "ddraw.h"
-#include "d3d.h"
-#include "win.h"
-#include "debugtools.h"
-#include "options.h"
-
-DEFAULT_DEBUG_CHANNEL(ddraw);
-
-#include "x11_private.h"
-
-#define DDPRIVATE(x) x11_dd_private *ddpriv = ((x11_dd_private*)(x)->d->private)
-#define DPPRIVATE(x) x11_dp_private *dppriv = ((x11_dp_private*)(x)->private)
-#define DSPRIVATE(x) x11_ds_private *dspriv = ((x11_ds_private*)(x)->private)
-
-static inline BOOL get_option( const char *name, BOOL def ) {
-    return PROFILE_GetWineIniBool( "x11drv", name, def );
-}
-
-int _common_depth_to_pixelformat(DWORD depth,LPDIRECTDRAW ddraw)
-{
-  ICOM_THIS(IDirectDrawImpl,ddraw);
-  XVisualInfo *vi;
-  XPixmapFormatValues *pf;
-  XVisualInfo vt;
-  int nvisuals, npixmap, i;
-  int match = 0;
-  int index = -2;
-  DDPIXELFORMAT *pixelformat = &(This->d->directdraw_pixelformat);
-  DDPIXELFORMAT *screen_pixelformat = &(This->d->screen_pixelformat);
-
-  This->d->pixel_convert = NULL;
-  This->d->palette_convert = NULL;
-
-  vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
-  pf = TSXListPixmapFormats(display, &npixmap);
-
-  for (i = 0; i < npixmap; i++) {
-    if (pf[i].depth == depth) {
-      int j;
-
-      for (j = 0; j < nvisuals; j++) {
-	if (vi[j].depth == pf[i].depth) {
-	  pixelformat->dwSize = sizeof(*pixelformat);
-	  if (depth == 8) {
-	    pixelformat->dwFlags = DDPF_PALETTEINDEXED8|DDPF_RGB;
-	    pixelformat->u1.dwRBitMask = 0;
-	    pixelformat->u2.dwGBitMask = 0;
-	    pixelformat->u3.dwBBitMask = 0;
-	  } else {
-	    pixelformat->dwFlags = DDPF_RGB;
-	    pixelformat->u1.dwRBitMask = vi[j].red_mask;
-	    pixelformat->u2.dwGBitMask = vi[j].green_mask;
-	    pixelformat->u3.dwBBitMask = vi[j].blue_mask;
-	  }
-	  pixelformat->dwFourCC = 0;
-	  pixelformat->u.dwRGBBitCount = pf[i].bits_per_pixel;
-	  pixelformat->u4.dwRGBAlphaBitMask= 0;
-	  *screen_pixelformat = *pixelformat;
-	  This->d->pixmap_depth = depth;
-	  match = 1;
-	  index = -1;
-	  goto clean_up_and_exit;
-	}
-      }
-      FIXME("No visual corresponding to pixmap format (depth=%ld)!\n",depth);
-    }
-  }
-
-  if (match == 0) {
-    /* We try now to find an emulated mode */
-    int c;
-
-    for (c = 0; c < sizeof(ModeEmulations) / sizeof(Convert); c++) {
-      if ((ModeEmulations[c].dest.depth == depth) &&
-          (ModeEmulations[c].dest.bpp == depth)
-      ) {
-	/* Found an emulation function, now tries to find a matching visual / pixel format pair */
-	for (i = 0; i < npixmap; i++) {
-	  if ((pf[i].depth == ModeEmulations[c].screen.depth) &&
-	      (pf[i].bits_per_pixel == ModeEmulations[c].screen.bpp)) {
-	    int j;
-
-	    for (j = 0; j < nvisuals; j++) {
-	      if (vi[j].depth == pf[i].depth) {
-		screen_pixelformat->dwSize = sizeof(*screen_pixelformat);
-		screen_pixelformat->dwFlags = DDPF_RGB;
-		screen_pixelformat->dwFourCC = 0;
-		screen_pixelformat->u.dwRGBBitCount = pf[i].bits_per_pixel;
-		screen_pixelformat->u1.dwRBitMask = vi[j].red_mask;
-		screen_pixelformat->u2.dwGBitMask = vi[j].green_mask;
-		screen_pixelformat->u3.dwBBitMask = vi[j].blue_mask;
-		screen_pixelformat->u4.dwRGBAlphaBitMask= 0;
-
-		pixelformat->dwSize = sizeof(*pixelformat);
-		pixelformat->dwFourCC = 0;
-		if (depth == 8) {
-		  pixelformat->dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
-		  pixelformat->u.dwRGBBitCount = 8;
-		  pixelformat->u1.dwRBitMask = 0;
-		  pixelformat->u2.dwGBitMask = 0;
-		  pixelformat->u3.dwBBitMask = 0;
-		} else {
-		  pixelformat->dwFlags = DDPF_RGB;
-		  pixelformat->u.dwRGBBitCount = ModeEmulations[c].dest.bpp;
-		  pixelformat->u1.dwRBitMask = ModeEmulations[c].dest.rmask;
-		  pixelformat->u2.dwGBitMask = ModeEmulations[c].dest.gmask;
-		  pixelformat->u3.dwBBitMask = ModeEmulations[c].dest.bmask;
-		}
-		pixelformat->u4.dwRGBAlphaBitMask= 0;    
-		This->d->pixmap_depth = vi[j].depth;
-		match = 2;
-		index = c;
-		This->d->pixel_convert  =ModeEmulations[c].funcs.pixel_convert;
-		This->d->palette_convert=ModeEmulations[c].funcs.palette_convert;
-		goto clean_up_and_exit;
-	      }
-	    }
-	  }
-	}
-      }
-    }
-    ERR("No emulation found for depth %ld!\n",depth);
-  }
-
-clean_up_and_exit:
-  TSXFree(vi);
-  TSXFree(pf);
-
-  return index;
-}
-
-#ifdef HAVE_LIBXXF86VM
-static XF86VidModeModeInfo *orig_mode = NULL;
-
-void
-xf86vmode_setdisplaymode(DWORD width, DWORD height) {
-    int i, mode_count;
-    XF86VidModeModeInfo **all_modes, *vidmode = NULL;
-    XF86VidModeModeLine mod_tmp;
-    /* int dotclock_tmp; */
-
-    /* save original video mode and set fullscreen if available */
-    orig_mode = (XF86VidModeModeInfo *)malloc(sizeof(XF86VidModeModeInfo));  
-    TSXF86VidModeGetModeLine(display, DefaultScreen(display), &orig_mode->dotclock, &mod_tmp);
-    orig_mode->hdisplay = mod_tmp.hdisplay; 
-    orig_mode->hsyncstart = mod_tmp.hsyncstart;
-    orig_mode->hsyncend = mod_tmp.hsyncend; 
-    orig_mode->htotal = mod_tmp.htotal;
-    orig_mode->vdisplay = mod_tmp.vdisplay; 
-    orig_mode->vsyncstart = mod_tmp.vsyncstart;
-    orig_mode->vsyncend = mod_tmp.vsyncend; 
-    orig_mode->vtotal = mod_tmp.vtotal;
-    orig_mode->flags = mod_tmp.flags; 
-	/* copy private data to our orig_mode structure */
-    orig_mode->privsize = mod_tmp.privsize;
-    if (orig_mode->privsize)
-    {
-      orig_mode->private = malloc(mod_tmp.privsize);
-      memcpy(orig_mode->private, mod_tmp.private, mod_tmp.privsize);
-    }
-
-    TSXF86VidModeGetAllModeLines(display,DefaultScreen(display),&mode_count,&all_modes);
-    for (i=0;i<mode_count;i++) {
-	if (all_modes[i]->hdisplay == width &&
-	    all_modes[i]->vdisplay == height
-	) {
-	    vidmode = (XF86VidModeModeInfo *)malloc(sizeof(XF86VidModeModeInfo));
-	    *vidmode = *(all_modes[i]);
-	    break;
-	} else
-	    TSXFree(all_modes[i]->private);
-    }
-    for (i++;i<mode_count;i++) TSXFree(all_modes[i]->private);
-	TSXFree(all_modes);
-
-    if (!vidmode)
-	WARN("Fullscreen mode not available!\n");
-
-    if (vidmode) {
-	TRACE("SwitchToMode(%dx%d)\n",vidmode->hdisplay,vidmode->vdisplay);
-	TSXF86VidModeSwitchToMode(display, DefaultScreen(display), vidmode);
-#if 0 /* This messes up my screen (XF86_Mach64, 3.3.2.3a) for some reason, and should now be unnecessary */
-	TSXF86VidModeSetViewPort(display, DefaultScreen(display), 0, 0);
-#endif
-    }
-}
-
-void xf86vmode_restore() {
-    if (!orig_mode)
-	return;
-    TSXF86VidModeSwitchToMode(display,DefaultScreen(display),orig_mode);
-    /* manually free the private data if it was allocated */
-    if (orig_mode->privsize)
-	free(orig_mode->private);		
-
-    free(orig_mode);
-    orig_mode = NULL;
-}
-#else
-void xf86vmode_setdisplaymode(DWORD width, DWORD height) {}
-void xf86vmode_restore() {}
-#endif
-
-
-/*******************************************************************************
- *				IDirectDraw
- */
-#ifdef HAVE_LIBXXSHM
-/* Error handlers for Image creation */
-static int XShmErrorHandler(Display *dpy, XErrorEvent *event) {
-    XShmErrorFlag = 1;
-    return 0;
-}
-
-static XImage *create_xshmimage(
-    IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf
-) {
-    DSPRIVATE(lpdsf);
-    DDPRIVATE(This);
-    XImage *img;
-    int (*WineXHandler)(Display *, XErrorEvent *);
-
-    img = TSXShmCreateImage(display,
-	DefaultVisualOfScreen(X11DRV_GetXScreen()),
-	This->d->pixmap_depth,
-	ZPixmap,
-	NULL,
-	&(dspriv->shminfo),
-	lpdsf->s.surface_desc.dwWidth,
-	lpdsf->s.surface_desc.dwHeight
-    );
-
-    if (img == NULL) {
-	FIXME("Couldn't create XShm image (due to X11 remote display or failure).\nReverting to standard X images !\n");
-	ddpriv->xshm_active = 0;
-	return NULL;
-    }
-
-    dspriv->shminfo.shmid = shmget( IPC_PRIVATE, img->bytes_per_line * img->height, IPC_CREAT|0777 );
-
-    if (dspriv->shminfo.shmid < 0) {
-	FIXME("Couldn't create shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
-	ddpriv->xshm_active = 0;
-	TSXDestroyImage(img);
-	return NULL;
-    }
-
-    dspriv->shminfo.shmaddr=img->data=(char*)shmat(dspriv->shminfo.shmid,0,0);
-
-    if (img->data == (char *) -1) {
-	FIXME("Couldn't attach shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
-	ddpriv->xshm_active = 0;
-	TSXDestroyImage(img);
-	shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
-	return NULL;
-    }
-    dspriv->shminfo.readOnly = False;
-
-    /* This is where things start to get trickier....
-     * First, we flush the current X connections to be sure to catch all
-     * non-XShm related errors
-     */
-    TSXSync(display, False);
-    /* Then we enter in the non-thread safe part of the tests */
-    EnterCriticalSection( &X11DRV_CritSection );
-
-    /* Reset the error flag, sets our new error handler and try to attach
-     * the surface
-     */
-    XShmErrorFlag = 0;
-    WineXHandler = XSetErrorHandler(XShmErrorHandler);
-    XShmAttach(display, &(dspriv->shminfo));
-    XSync(display, False);
-
-    /* Check the error flag */
-    if (XShmErrorFlag) {
-	/* An error occured */
-	XFlush(display);
-	XShmErrorFlag = 0;
-	XDestroyImage(img);
-	shmdt(dspriv->shminfo.shmaddr);
-	shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
-	XSetErrorHandler(WineXHandler);
-
-	FIXME("Couldn't attach shared memory segment to X server (due to X11 remote display or failure).\nReverting to standard X images !\n");
-	ddpriv->xshm_active = 0;
-
-	/* Leave the critical section */
-	LeaveCriticalSection( &X11DRV_CritSection );
-	return NULL;
-    }
-    /* Here, to be REALLY sure, I should do a XShmPutImage to check if
-     * this works, but it may be a bit overkill....
-     */
-    XSetErrorHandler(WineXHandler);
-    LeaveCriticalSection( &X11DRV_CritSection );
-
-    shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
-
-    if (This->d->pixel_convert != NULL) {
-	int bpp = PFGET_BPP(This->d->directdraw_pixelformat);
-	lpdsf->s.surface_desc.u1.lpSurface = VirtualAlloc(
-	    NULL,
-	    lpdsf->s.surface_desc.dwWidth *
-	    lpdsf->s.surface_desc.dwHeight *
-	    bpp,
-	    MEM_RESERVE | MEM_COMMIT,
-	    PAGE_READWRITE
-	);
-    } else {
-	lpdsf->s.surface_desc.u1.lpSurface = img->data;
-	VirtualAlloc(img->data, img->bytes_per_line * img->height, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
-    }
-    return img;
-}
-#endif /* HAVE_LIBXXSHM */
-
-static XImage *create_ximage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf) {
-    XImage *img = NULL;
-    DDPRIVATE(This);
-    void *img_data;
-    int bpp = PFGET_BPP(This->d->directdraw_pixelformat);
-    int screen_bpp = PFGET_BPP(This->d->screen_pixelformat);
-
-#ifdef HAVE_LIBXXSHM
-    if (ddpriv->xshm_active)
-	img = create_xshmimage(This, lpdsf);
-
-    if (img == NULL) {
-#endif
-    /* Allocate surface memory */
-	lpdsf->s.surface_desc.u1.lpSurface = VirtualAlloc(
-	    NULL,
-	    lpdsf->s.surface_desc.dwWidth *
-	    lpdsf->s.surface_desc.dwHeight *
-	    bpp,
-	    MEM_RESERVE | MEM_COMMIT,
-	    PAGE_READWRITE
-	);
-
-	if (This->d->pixel_convert != NULL)
-	    img_data = VirtualAlloc(
-		NULL,
-		lpdsf->s.surface_desc.dwWidth *
-		lpdsf->s.surface_desc.dwHeight *
-		screen_bpp,
-		MEM_RESERVE | MEM_COMMIT,
-		PAGE_READWRITE
-	    );
-        else
-	    img_data = lpdsf->s.surface_desc.u1.lpSurface;
-
-	/* In this case, create an XImage */
-	img = TSXCreateImage(display,
-	    DefaultVisualOfScreen(X11DRV_GetXScreen()),
-	    This->d->pixmap_depth,
-	    ZPixmap,
-	    0,
-	    img_data,
-	    lpdsf->s.surface_desc.dwWidth,
-	    lpdsf->s.surface_desc.dwHeight,
-	    32,
-	    lpdsf->s.surface_desc.dwWidth*screen_bpp
-	);
-#ifdef HAVE_LIBXXSHM
-    }
-#endif
-    if (This->d->pixel_convert != NULL)
-	lpdsf->s.surface_desc.lPitch = bpp*lpdsf->s.surface_desc.dwWidth;
-    else
-	lpdsf->s.surface_desc.lPitch = img->bytes_per_line;
-    return img;
-}
-
-#ifdef HAVE_XVIDEO
-#ifdef HAVE_LIBXXSHM
-static XvImage *create_xvshmimage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf) {
-    DSPRIVATE(lpdsf);
-    DDPRIVATE(This);
-    XvImage *img;
-    int (*WineXHandler)(Display *, XErrorEvent *);
-
-    img = TSXvShmCreateImage(display,
-			     ddpriv->port_id,
-			     (int) lpdsf->s.surface_desc.ddpfPixelFormat.dwFourCC,
-			     NULL,
-			     lpdsf->s.surface_desc.dwWidth,
-			     lpdsf->s.surface_desc.dwHeight,
-			     &(dspriv->shminfo));
-    
-    if (img == NULL) {
-	FIXME("Couldn't create XShm XvImage (due to X11 remote display or failure).\nReverting to standard X images !\n");
-	ddpriv->xshm_active = 0;
-	return NULL;
-    }
-
-    dspriv->shminfo.shmid = shmget( IPC_PRIVATE, img->data_size, IPC_CREAT|0777 );
-
-    if (dspriv->shminfo.shmid < 0) {
-	FIXME("Couldn't create shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
-	ddpriv->xshm_active = 0;
-	TSXFree(img);
-	return NULL;
-    }
-
-    dspriv->shminfo.shmaddr=img->data=(char*)shmat(dspriv->shminfo.shmid,0,0);
-
-    if (img->data == (char *) -1) {
-	FIXME("Couldn't attach shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
-	ddpriv->xshm_active = 0;
-	TSXFree(img);
-	shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
-	return NULL;
-    }
-    dspriv->shminfo.readOnly = False;
-
-    /* This is where things start to get trickier....
-     * First, we flush the current X connections to be sure to catch all
-     * non-XShm related errors
-     */
-    TSXSync(display, False);
-    /* Then we enter in the non-thread safe part of the tests */
-    EnterCriticalSection( &X11DRV_CritSection );
-
-    /* Reset the error flag, sets our new error handler and try to attach
-     * the surface
-     */
-    XShmErrorFlag = 0;
-    WineXHandler = XSetErrorHandler(XShmErrorHandler);
-    XShmAttach(display, &(dspriv->shminfo));
-    XSync(display, False);
-
-    /* Check the error flag */
-    if (XShmErrorFlag) {
-	/* An error occured */
-	XFlush(display);
-	XShmErrorFlag = 0;
-	XFree(img);
-	shmdt(dspriv->shminfo.shmaddr);
-	shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
-	XSetErrorHandler(WineXHandler);
-
-	FIXME("Couldn't attach shared memory segment to X server (due to X11 remote display or failure).\nReverting to standard X images !\n");
-	ddpriv->xshm_active = 0;
-
-	/* Leave the critical section */
-	LeaveCriticalSection( &X11DRV_CritSection );
-	return NULL;
-    }
-    /* Here, to be REALLY sure, I should do a XShmPutImage to check if
-     * this works, but it may be a bit overkill....
-     */
-    XSetErrorHandler(WineXHandler);
-    LeaveCriticalSection( &X11DRV_CritSection );
-
-    shmctl(dspriv->shminfo.shmid, IPC_RMID, 0);
-
-    lpdsf->s.surface_desc.u1.lpSurface = img->data;
-    VirtualAlloc(img->data, img->data_size, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
-
-    return img;
-}
-#endif
-
-static XvImage *create_xvimage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf, HRESULT *err_code) {
-    XvImage *img = NULL;
-    DDPRIVATE(This);
-    void *img_data;
-    XvImageFormatValues	*fo;
-    int formats, i;
-    int bpp = PFGET_BPP(lpdsf->s.surface_desc.ddpfPixelFormat);
-    
-    *err_code = DDERR_OUTOFVIDEOMEMORY;
-    
-    if (!(lpdsf->s.surface_desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
-      /* Hmmm, overlay without FOURCC code.. Baaaaaad */
-      ERR("Overlay without a FOURCC pixel format !\n");
-      *err_code = DDERR_INVALIDPIXELFORMAT;
-      return NULL;
-    }
-      
-    /* First, find out if we support this PixelFormat.
-       I make the assumption here that the id of the XvImage format is the
-       same as the Windows FOURCC code. */
-    fo = TSXvListImageFormats(display, ddpriv->port_id, &formats);
-    for (i = 0; i < formats; i++)
-      if (fo[i].id == lpdsf->s.surface_desc.ddpfPixelFormat.dwFourCC) break;
-    if (fo)
-      TSXFree(fo);
-    
-    if (i == formats) {
-      ERR("FOURCC code not supported by the video card !\n");
-      *err_code = DDERR_INVALIDPIXELFORMAT;
-      return NULL;
-    }
-    
-#ifdef HAVE_LIBXXSHM
-    if (ddpriv->xshm_active)
-	img = create_xvshmimage(This, lpdsf);
-
-    if (img == NULL) {
-#endif
-      /* Allocate surface memory */
-      lpdsf->s.surface_desc.u1.lpSurface =
-	VirtualAlloc(NULL,
-		     lpdsf->s.surface_desc.dwWidth *
-		     lpdsf->s.surface_desc.dwHeight *
-		     bpp,
-		     MEM_RESERVE | MEM_COMMIT,
-		     PAGE_READWRITE);
-      img_data = lpdsf->s.surface_desc.u1.lpSurface;
-
-      /* In this case, create an XvImage */
-      img = TSXvCreateImage(display,
-			    ddpriv->port_id,
-			    (int) lpdsf->s.surface_desc.ddpfPixelFormat.dwFourCC,
-			    img_data,
-			    lpdsf->s.surface_desc.dwWidth,
-			    lpdsf->s.surface_desc.dwHeight);
-#ifdef HAVE_LIBXXSHM
-    }
-#endif
-    lpdsf->s.surface_desc.lPitch = ((XvImage *) img)->pitches[0];
-    return img;
-}
-#else
-static XvImage *create_xvimage(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* lpdsf, HRESULT *err_code) {
-  *err_code = DDERR_INVALIDPIXELFORMAT;
-  return NULL;
-}
-#endif
-
-ULONG WINAPI Xlib_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
-
-    if (!--(This->ref)) {
-	if (!--(This->d->ref)) {
-	    if (This->d->window && GetPropA(This->d->window,ddProp))
-		DestroyWindow(This->d->window);
-	    HeapFree(GetProcessHeap(),0,This->d);
-	}
-	HeapFree(GetProcessHeap(),0,This);
-	xf86vmode_restore();
-	return S_OK;
-    }
-    return This->ref;
-}
-
-static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreateSurface(
-    LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,
-    IUnknown *lpunk
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    IDirectDrawSurfaceImpl* dsurf;
-    x11_ds_private	*dspriv;
-
-    TRACE("(%p)->CreateSurface(%p,%p,%p)\n", This,lpddsd,lpdsf,lpunk);
-
-    if (TRACE_ON(ddraw)) _dump_surface_desc(lpddsd);
-
-    *lpdsf = HeapAlloc(
-    	GetProcessHeap(),
-	HEAP_ZERO_MEMORY,
-	sizeof(IDirectDrawSurfaceImpl)
-    );
-    dsurf = (IDirectDrawSurfaceImpl*)*lpdsf;
-    dsurf->ref                 = 1;
-    dsurf->private = HeapAlloc(
-	    GetProcessHeap(),
-	    HEAP_ZERO_MEMORY,
-	    sizeof(x11_ds_private)
-    );
-    ICOM_VTBL(dsurf) = (ICOM_VTABLE(IDirectDrawSurface)*)&xlib_dds4vt;
-    dspriv = (x11_ds_private*)dsurf->private;
-
-    dsurf->s.ddraw	= This;
-    IDirectDraw2_AddRef(iface);
-
-    dsurf->s.palette	= NULL;
-    dsurf->s.lpClipper	= NULL;
-    dspriv->is_overlay  = FALSE;
-    dspriv->info.image	= NULL; /* This is for off-screen buffers */
-
-    /* Copy the surface description */
-    dsurf->s.surface_desc = *lpddsd;
-
-    if (!(lpddsd->dwFlags & DDSD_WIDTH))
-	dsurf->s.surface_desc.dwWidth  = This->d->width;
-    if (!(lpddsd->dwFlags & DDSD_HEIGHT))
-	dsurf->s.surface_desc.dwHeight = This->d->height;
-    dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
-
-    /* Check if this a 'primary surface' or an overlay */
-    if ((lpddsd->dwFlags & DDSD_CAPS) && 
-	((lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) ||
-	 (lpddsd->ddsCaps.dwCaps & DDSCAPS_OVERLAY))
-    ) {
-	/* Add flags if there were not present */
-	dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
-	dsurf->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
-
-	if (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) {
-	  dsurf->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
-	  dsurf->s.surface_desc.ddpfPixelFormat = This->d->directdraw_pixelformat;
-	  dsurf->s.surface_desc.dwWidth = This->d->width;
-	  dsurf->s.surface_desc.dwHeight = This->d->height;
-	} else {
-	  dspriv->is_overlay = TRUE;
-	  /* In the case of Overlay surfaces, copy the one provided by the application */
-	  dsurf->s.surface_desc.ddpfPixelFormat = lpddsd->ddpfPixelFormat;
-	}
-	
-	if (lpddsd->ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
-	  HRESULT err_code;
-	  TRACE("using an XvImage for the overlay (%p)\n", dsurf);
-	  dspriv->info.overlay.image = create_xvimage(This,(IDirectDrawSurface4Impl*)dsurf, &err_code);
-	  if (dspriv->info.overlay.image == NULL)
-	    return err_code;
-	} else {
-	  TRACE("using standard XImage for a primary surface (%p)\n", dsurf);
-	  /* Create the XImage */
-	  dspriv->info.image = create_ximage(This,(IDirectDrawSurface4Impl*)dsurf);
-	  if (dspriv->info.image == NULL)
-	    return DDERR_OUTOFMEMORY;
-	}
-
-	/* Check for backbuffers */
-	if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
-	    IDirectDrawSurface4Impl*	back;
-	    int	i;
-
-	    for (i=lpddsd->dwBackBufferCount;i--;) {
-		x11_ds_private *bspriv;
-		back = (IDirectDrawSurface4Impl*)HeapAlloc(
-		    GetProcessHeap(),
-		    HEAP_ZERO_MEMORY,
-		    sizeof(IDirectDrawSurface4Impl)
-		);
-		TRACE("allocated back-buffer (%p)\n", back);
-
-		IDirectDraw2_AddRef(iface);
-		back->s.ddraw = This;
-		
-		back->ref = 1;
-		ICOM_VTBL(back)=(ICOM_VTABLE(IDirectDrawSurface4)*)&xlib_dds4vt;
-		/* Copy the surface description from the front buffer */
-		back->s.surface_desc = dsurf->s.surface_desc;
-		back->s.surface_desc.u1.lpSurface = NULL;
-		
-		back->private = HeapAlloc(
-		    GetProcessHeap(),
-		    HEAP_ZERO_MEMORY,
-		    sizeof(x11_ds_private)
-		);
-		bspriv = (x11_ds_private*)back->private;
-
-		/* Create the XImage. */
-		if (lpddsd->ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
-		  HRESULT err_code;
-		  dspriv->is_overlay = TRUE;
-		  bspriv->info.overlay.image = create_xvimage(This, back, &err_code);
-		  if (bspriv->info.overlay.image == NULL)
-		    return err_code;
-		} else {
-		  bspriv->info.image = create_ximage(This, back);
-		  if (bspriv->info.image == NULL)
-		    return DDERR_OUTOFMEMORY;
-		}
-		TRACE("bspriv = %p\n",bspriv);
-
-		/* Add relevant info to front and back buffers */
-		/* FIXME: backbuffer/frontbuffer handling broken here, but
-		 * will be fixed up in _Flip().
-		 */
-		SDDSCAPS(dsurf) |= DDSCAPS_FRONTBUFFER;
-		SDDSCAPS(back) |= DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY|DDSCAPS_FLIP;
-		back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
-		SDDSCAPS(back) &= ~(DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE);
-		TRACE("attaching surface %p to %p\n",back,*lpdsf);
-		IDirectDrawSurface4_AddAttachedSurface((LPDIRECTDRAWSURFACE4)(*lpdsf),(LPDIRECTDRAWSURFACE4)back);
-	    }
-	}
-    } else {
-	/* There is no Xlib-specific code here...
-	 * Go to the common surface creation function
-	 */
-	return common_off_screen_CreateSurface(This,dsurf);
-    }
-    return DD_OK;
-}
-
-/* 
- * The Xlib Implementation tries to use the passed hwnd as drawing window,
- * even when the approbiate bitmasks are not specified.
- */
-static HRESULT WINAPI Xlib_IDirectDraw2Impl_SetCooperativeLevel(
-    LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDPRIVATE(This);
-
-    FIXME("(%p)->(%08lx,%08lx)\n",This,(DWORD)hwnd,cooplevel);
-    if (TRACE_ON(ddraw))
-	_dump_cooperativelevel(cooplevel);
-    This->d->mainWindow = hwnd;
-
-    /* This will be overwritten in the case of Full Screen mode.
-       Windowed games could work with that :-) */
-    if (hwnd) {
-	WND *tmpWnd = WIN_FindWndPtr(hwnd);
-	ddpriv->drawable  = X11DRV_WND_GetXWindow(tmpWnd);
-	WIN_ReleaseWndPtr(tmpWnd);
-
-	if( !ddpriv->drawable ) {
-	    ddpriv->drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
-	    WIN_ReleaseDesktop();
-	}
-	TRACE("Setting drawable to %ld\n", ddpriv->drawable);
-    }
-    return DD_OK;
-}
-
-static HRESULT WINAPI Xlib_IDirectDrawImpl_SetDisplayMode(
-    LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
-) {
-    ICOM_THIS(IDirectDrawImpl,iface);
-    DDPRIVATE(This);
-    char	buf[200];
-    WND *tmpWnd;
-    int c;
-
-    TRACE("(%p)->SetDisplayMode(%ld,%ld,%ld)\n",
-		  This, width, height, depth);
-
-    switch ((c = _common_depth_to_pixelformat(depth,iface))) {
-    case -2:
-      sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
-      MessageBoxA(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
-      return DDERR_UNSUPPORTEDMODE;
-    case -1:
-      /* No conversion. Good. */
-      break;
-    default:
-      DPRINTF("DirectDraw warning: running in depth-conversion mode %d. Should run using a %ld depth for optimal performances.\n", c,depth);
-    }
-	
-    This->d->width	= width;
-    This->d->height	= height;
-
-    _common_IDirectDrawImpl_SetDisplayMode(This);
-
-    xf86vmode_setdisplaymode(width,height);
-
-    tmpWnd = WIN_FindWndPtr(This->d->window);
-    This->d->paintable = 1;
-    ddpriv->drawable  = ((X11DRV_WND_DATA *) tmpWnd->pDriverData)->window;
-    WIN_ReleaseWndPtr(tmpWnd);
-
-    /* We don't have a context for this window. Host off the desktop */
-    if( !ddpriv->drawable )
-    {
-       ddpriv->drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
-	WIN_ReleaseDesktop();
-    }
-    TRACE("Setting drawable to %ld\n", ddpriv->drawable);
-
-    if (get_option( "DXGrab", 0 )) {
-	/* Confine cursor movement (risky, but the user asked for it) */
-	TSXGrabPointer(display, ddpriv->drawable, True, 0, GrabModeAsync, GrabModeAsync, ddpriv->drawable, None, CurrentTime);
-    }
-
-    return DD_OK;
-}
-
-static void fill_caps(LPDDCAPS caps, x11_dd_private *x11ddp) {
-  /* This function tries to fill the capabilities of Wine's DDraw implementation.
-     Need to be fixed, though.. */
-  if (caps == NULL)
-    return;
-
-  caps->dwSize = sizeof(*caps);
-  caps->dwCaps = DDCAPS_ALPHA | DDCAPS_BLT | DDCAPS_BLTSTRETCH | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL | DDCAPS_CANBLTSYSMEM |  DDCAPS_COLORKEY | DDCAPS_PALETTE /*| DDCAPS_NOHARDWARE*/;
-  caps->dwCaps2 = DDCAPS2_CERTIFIED | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_WIDESURFACES;
-  caps->dwCKeyCaps = 0xFFFFFFFF; /* Should put real caps here one day... */
-  caps->dwFXCaps = 0;
-  caps->dwFXAlphaCaps = 0;
-  caps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
-  caps->dwSVCaps = 0;
-  caps->dwZBufferBitDepths = DDBD_16;
-  /* I put here 8 Mo so that D3D applications will believe they have enough memory
-     to put textures in video memory.
-     BTW, is this only frame buffer memory or also texture memory (for Voodoo boards
-     for example) ? */
-  caps->dwVidMemTotal = 8192 * 1024;
-  caps->dwVidMemFree = 8192 * 1024;
-  /* These are all the supported capabilities of the surfaces */
-  caps->ddsCaps.dwCaps = DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
-    DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
-      DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
-	DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
-#ifdef HAVE_OPENGL
-  caps->dwCaps |= DDCAPS_3D | DDCAPS_ZBLTS;
-  caps->dwCaps2 |=  DDCAPS2_NO2DDURING3DSCENE;
-  caps->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
-#endif
-
-#ifdef HAVE_XVIDEO
-  if (x11ddp->xvideo_active) {
-    caps->dwCaps |= DDCAPS_OVERLAY | DDCAPS_OVERLAYFOURCC | DDCAPS_OVERLAYSTRETCH | DDCAPS_BLTFOURCC;
-    caps->dwCaps2 |= DDCAPS2_VIDEOPORT;
-    caps->dwMaxVisibleOverlays = 16;
-    caps->dwCurrVisibleOverlays = 0;
-    caps->dwMinOverlayStretch = 1; /* Apparently there is no 'down' stretching in XVideo, but well, Windows
-				      Media player refuses to work when I put 1000 here :-/ */
-    caps->dwMaxOverlayStretch = 100000; /* This is a 'bogus' value, I do not know the maximum stretching */
-    TSXvListImageFormats(display, x11ddp->port_id, (unsigned int *) &(caps->dwNumFourCCCodes));
-    caps->ddsCaps.dwCaps |= DDSCAPS_OVERLAY;
-  }
-#endif
-}
-
-static HRESULT WINAPI Xlib_IDirectDraw2Impl_GetCaps(
-    LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
-)  {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    DDPRIVATE(This);
-    TRACE("(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
-
-    /* Put the same caps for the two capabilities */
-    fill_caps(caps1, ddpriv);
-    fill_caps(caps2, ddpriv);
-
-    return DD_OK;
-}
-
-static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreatePalette(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,
-    LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    IDirectDrawPaletteImpl** ilpddpal=(IDirectDrawPaletteImpl**)lpddpal;
-    int xsize;
-    HRESULT res;
-
-    TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ilpddpal,lpunk);
-    res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,ilpddpal,lpunk,&xsize);
-    if (res != 0)
-	return res;
-    (*ilpddpal)->private = HeapAlloc(
-	GetProcessHeap(),
-	HEAP_ZERO_MEMORY,
-	sizeof(x11_dp_private)
-    );
-    ICOM_VTBL(*ilpddpal) = &xlib_ddpalvt;
-    return DD_OK;
-}
-
-static HRESULT WINAPI Xlib_IDirectDraw2Impl_QueryInterface(
-    LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-
-    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
-    if ( IsEqualGUID( &IID_IUnknown, refiid ) ) {
-	*obj = This;
-	IDirectDraw2_AddRef(iface);
-
-	TRACE("  Creating IUnknown interface (%p)\n", *obj);
-	
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirectDraw, refiid ) ) {
-	IDirectDrawImpl	*dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
-	IDirectDraw2_AddRef(iface);
-
-	dd->ref = 1;ICOM_VTBL(dd) = &xlib_ddvt;dd->d = This->d;This->d->ref++;
-	*obj = dd;
-
-	TRACE("  Creating IDirectDraw interface (%p)\n", *obj);
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) ) {
-	IDirectDraw2Impl *dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
-	IDirectDraw2_AddRef(iface);
-
-	dd->ref = 1;ICOM_VTBL(dd) = &xlib_dd2vt;dd->d = This->d;This->d->ref++;
-	*obj = dd;
-
-	TRACE("  Creating IDirectDraw2 interface (%p)\n", *obj);
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) ) {
-	IDirectDraw4Impl *dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
-	dd->ref = 1;ICOM_VTBL(dd) = &xlib_dd4vt;dd->d = This->d;This->d->ref++;
-	*obj = dd;
-
-	IDirectDraw4_AddRef(iface);
-	TRACE("  Creating IDirectDraw4 interface (%p)\n", *obj);
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirectDraw7, refiid ) ) {
-	IDirectDraw4Impl *dd = HeapAlloc(GetProcessHeap(),0,sizeof(*dd));
-	dd->ref = 1;ICOM_VTBL(dd) = (ICOM_VTABLE(IDirectDraw4)*)&xlib_dd7vt;dd->d = This->d;This->d->ref++;
-	*obj = dd;
-
-	IDirectDraw7_AddRef(iface);
-	FIXME("  Creating IDirectDraw7 interface by reusing DirectDraw4!(%p)\n", *obj);
-	return S_OK;
-    }
-#ifdef HAVE_OPENGL
-    if ( IsEqualGUID( &IID_IDirect3D, refiid ) )
-	return create_direct3d(obj,This);
-    if ( IsEqualGUID( &IID_IDirect3D2, refiid ) )
-	return create_direct3d2(obj,This);
-    if ( IsEqualGUID( &IID_IDirect3D3, refiid ) ) 
-        return create_direct3d3(obj,This);
-#else
-    if ( IsEqualGUID( &IID_IDirect3D, refiid ) ||
-         IsEqualGUID( &IID_IDirect3D2, refiid ) ||
-         IsEqualGUID( &IID_IDirect3D3, refiid )
-       )
-    {
-       ERR( "Cannot provide 3D support without OpenGL/Mesa installed\n" );
-    } 
-#endif
-    FIXME("(%p):interface for IID %s _NOT_ found!\n",This,debugstr_guid(refiid));
-    return OLE_E_ENUM_NOMORE;
-}
-
-static HRESULT WINAPI Xlib_IDirectDraw2Impl_EnumDisplayModes(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
-) {
-  ICOM_THIS(IDirectDraw2Impl,iface);
-  XVisualInfo *vi;
-  XPixmapFormatValues *pf;
-  XVisualInfo vt;
-  int xbpp = 1, nvisuals, npixmap, i, emu;
-  int has_mode[]  = { 0,  0,  0,  0 };
-  int has_depth[] = { 8, 15, 16, 24 };
-  DDSURFACEDESC	ddsfd;
-  static struct {
-	int w,h;
-  } modes[] = { /* some of the usual modes */
-	{512,384},
-	{640,400},
-	{640,480},
-	{800,600},
-	{1024,768},
-	{1280,1024}
-  };
-  DWORD maxWidth, maxHeight;
-
-  TRACE("(%p)->(0x%08lx,%p,%p,%p)\n",This,dwFlags,lpddsfd,context,modescb);
-  ddsfd.dwSize = sizeof(ddsfd);
-  ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_CAPS|DDSD_PITCH;
-  if (dwFlags & DDEDM_REFRESHRATES) {
-    ddsfd.dwFlags |= DDSD_REFRESHRATE;
-    ddsfd.u.dwRefreshRate = 60;
-  }
-  maxWidth = GetSystemMetrics(SM_CXSCREEN);
-  maxHeight = GetSystemMetrics(SM_CYSCREEN);
-  
-  vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
-  pf = TSXListPixmapFormats(display, &npixmap);
-
-  i = 0;
-  emu = 0;
-  while ((i < npixmap) || (emu != 4)) {
-    int mode_index = 0;
-    int send_mode = 0;
-    int j;
-
-    if (i < npixmap) {
-      for (j = 0; j < 4; j++) {
-	if (has_depth[j] == pf[i].depth) {
-	  mode_index = j;
-	  break;
-	}
-      }
-      if (j == 4) {
-	i++;
-	continue;
-      }
-      
-
-      if (has_mode[mode_index] == 0) {
-	if (mode_index == 0) {
-	  send_mode = 1;
-
-	  ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE;
-	  ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
-	  ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
-	  ddsfd.ddpfPixelFormat.dwFourCC = 0;
-	  ddsfd.ddpfPixelFormat.u.dwRGBBitCount = 8;
-	  ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0;
-	  ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0;
-	  ddsfd.ddpfPixelFormat.u3.dwBBitMask = 0;
-	  ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
-
-	  xbpp = 1;
-	  
-	  has_mode[mode_index] = 1;
-	} else {
-	  /* All the 'true color' depths (15, 16 and 24)
-	     First, find the corresponding visual to extract the bit masks */
-	  for (j = 0; j < nvisuals; j++) {
-	    if (vi[j].depth == pf[i].depth) {
-	      ddsfd.ddsCaps.dwCaps = 0;
-	      ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
-	      ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
-	      ddsfd.ddpfPixelFormat.dwFourCC = 0;
-	      ddsfd.ddpfPixelFormat.u.dwRGBBitCount = pf[i].bits_per_pixel;
-	      ddsfd.ddpfPixelFormat.u1.dwRBitMask = vi[j].red_mask;
-	      ddsfd.ddpfPixelFormat.u2.dwGBitMask = vi[j].green_mask;
-	      ddsfd.ddpfPixelFormat.u3.dwBBitMask = vi[j].blue_mask;
-	      ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
-
-	      xbpp = pf[i].bits_per_pixel/8;
-
-	      send_mode = 1;
-		  has_mode[mode_index] = 1;
-	      break;
-	    }
-	  }
-	  if (j == nvisuals)
-	    WARN("Did not find visual corresponding to the pixmap format !\n");
-	}
-      }
-      i++;
-    } else {
-      /* Now to emulated modes */
-      if (has_mode[emu] == 0) {
-	int c;
-	int l;
-	int depth = has_depth[emu];
-      
-	for (c = 0; (c < sizeof(ModeEmulations) / sizeof(Convert)) && (send_mode == 0); c++) {
-	  if (ModeEmulations[c].dest.depth == depth) {
-	    /* Found an emulation function, now tries to find a matching visual / pixel format pair */
-	    for (l = 0; (l < npixmap) && (send_mode == 0); l++) {
-	      if ((pf[l].depth == ModeEmulations[c].screen.depth) &&
-		  (pf[l].bits_per_pixel == ModeEmulations[c].screen.bpp)) {
-		int j;
-		for (j = 0; (j < nvisuals) && (send_mode == 0); j++) {
-		  if ((vi[j].depth == pf[l].depth) &&
-		      (vi[j].red_mask == ModeEmulations[c].screen.rmask) &&
-		      (vi[j].green_mask == ModeEmulations[c].screen.gmask) &&
-		      (vi[j].blue_mask == ModeEmulations[c].screen.bmask)) {
-		    ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
-		    ddsfd.ddpfPixelFormat.dwFourCC = 0;
-		    if (depth == 8) {
-		      ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
-		      ddsfd.ddpfPixelFormat.u.dwRGBBitCount = 8;
-		      ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0;
-		      ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0;
-		      ddsfd.ddpfPixelFormat.u3.dwBBitMask = 0;
-		    } else {
-		      ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
-		      ddsfd.ddpfPixelFormat.u.dwRGBBitCount = ModeEmulations[c].dest.bpp;
-		      ddsfd.ddpfPixelFormat.u1.dwRBitMask = ModeEmulations[c].dest.rmask;
-		      ddsfd.ddpfPixelFormat.u2.dwGBitMask = ModeEmulations[c].dest.gmask;
-		      ddsfd.ddpfPixelFormat.u3.dwBBitMask = ModeEmulations[c].dest.bmask;
-		    }
-		    ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
-		    send_mode = 1;
-		  }
-		  
-		  if (send_mode == 0)
-		    WARN("No visual corresponding to pixmap format !\n");
-		}
-	      }
-	    }
-          }
-	}
-      }
-
-      emu++;
-    }
-
-    if (send_mode) {
-      int mode;
-
-      if (TRACE_ON(ddraw)) {
-	TRACE("Enumerating with pixel format : \n");
-	_dump_pixelformat(&(ddsfd.ddpfPixelFormat));
-	DPRINTF("\n");
-      }
-      
-      for (mode = 0; mode < sizeof(modes)/sizeof(modes[0]); mode++) {
-	/* Do not enumerate modes we cannot handle anyway */
-	if ((modes[mode].w > maxWidth) || (modes[mode].h > maxHeight))
-	  break;
-
-	ddsfd.dwWidth = modes[mode].w;
-	ddsfd.dwHeight= modes[mode].h;
-	ddsfd.lPitch  = ddsfd.dwWidth * xbpp;
-	
-	/* Now, send the mode description to the application */
-	TRACE(" - mode %4ld - %4ld\n", ddsfd.dwWidth, ddsfd.dwHeight);
-	if (!modescb(&ddsfd, context))
-	  goto exit_enum;
-      }
-
-      if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
-	/* modeX is not standard VGA */
-	ddsfd.dwWidth = 320;
-	ddsfd.dwHeight = 200;
-	ddsfd.lPitch  = 320 * xbpp;
-	if (!modescb(&ddsfd, context))
-	  goto exit_enum;
-      }
-    }
-  }
- exit_enum:
-  TSXFree(vi);
-  TSXFree(pf);
-
-  return DD_OK;
-}
-
-HRESULT WINAPI Xlib_IDirectDraw2Impl_GetFourCCCodes(
-    LPDIRECTDRAW2 iface,LPDWORD lpNumCodes, LPDWORD lpCodes
-) {
-#ifdef HAVE_XVIDEO
-  ICOM_THIS(IDirectDraw2Impl,iface);
-  DDPRIVATE(This);
-  XvImageFormatValues *fo;
-  int num_codes;
-  
-  TRACE("(%p,%p,%p) - %ld slots available\n",This, lpNumCodes, lpCodes, *lpNumCodes);
-  
-  fo = TSXvListImageFormats(display, ddpriv->port_id, &num_codes);
-  if (lpCodes != NULL) {
-    /* Fill in the FourCC table */
-    int i;
-    for (i = 0; i < *lpNumCodes; i++) lpCodes[i] = fo[i].id;
-  }
-  if (fo) {
-    *lpNumCodes = num_codes;
-    TSXFree(fo);
-  } else {
-    *lpNumCodes = 0; /* Not sure if X fills this variable in the error case */
-  }
-  
-  return DD_OK;
-#else
-  return IDirectDraw2Impl_GetFourCCCodes(iface, lpNumCodes, lpCodes);
-#endif
-}
-
-/* Note: Hack so we can reuse the old functions without compiler warnings */
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)	(typeof(xlib_ddvt.fn##fun))
-#else
-# define XCAST(fun)	(void *)
-#endif
-
-ICOM_VTABLE(IDirectDraw) xlib_ddvt = {
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
-    XCAST(AddRef)IDirectDraw2Impl_AddRef,
-    XCAST(Release)Xlib_IDirectDraw2Impl_Release,
-    XCAST(Compact)IDirectDraw2Impl_Compact,
-    XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
-    XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
-    XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
-    XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
-    XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
-    XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
-    XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
-    XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
-    XCAST(GetDisplayMode)IDirectDraw2Impl_GetDisplayMode,
-    XCAST(GetFourCCCodes)Xlib_IDirectDraw2Impl_GetFourCCCodes,
-    XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
-    XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
-    XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
-    XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
-    XCAST(Initialize)IDirectDraw2Impl_Initialize,
-    XCAST(RestoreDisplayMode)IDirectDraw2Impl_RestoreDisplayMode,
-    XCAST(SetCooperativeLevel)Xlib_IDirectDraw2Impl_SetCooperativeLevel,
-    Xlib_IDirectDrawImpl_SetDisplayMode,
-    XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
-};
-
-#undef XCAST
-
-/*****************************************************************************
- * 	IDirectDraw2
- *
- */
-
-static HRESULT WINAPI Xlib_IDirectDraw2Impl_SetDisplayMode(
-    LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD dwRefreshRate,DWORD dwFlags
-) {
-    FIXME( "Ignored parameters (0x%08lx,0x%08lx)\n", dwRefreshRate, dwFlags ); 
-    return Xlib_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
-}
-
-static HRESULT WINAPI Xlib_IDirectDraw2Impl_GetAvailableVidMem(
-    LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
-) {
-    ICOM_THIS(IDirectDraw2Impl,iface);
-    TRACE("(%p)->(%p,%p,%p)\n",This,ddscaps,total,free);
-    if (total) *total = 16* 1024 * 1024;
-    if (free) *free = 16* 1024 * 1024;
-    return DD_OK;
-}
-
-ICOM_VTABLE(IDirectDraw2) xlib_dd2vt = {
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    Xlib_IDirectDraw2Impl_QueryInterface,
-    IDirectDraw2Impl_AddRef,
-    Xlib_IDirectDraw2Impl_Release,
-    IDirectDraw2Impl_Compact,
-    IDirectDraw2Impl_CreateClipper,
-    Xlib_IDirectDraw2Impl_CreatePalette,
-    Xlib_IDirectDraw2Impl_CreateSurface,
-    IDirectDraw2Impl_DuplicateSurface,
-    Xlib_IDirectDraw2Impl_EnumDisplayModes,
-    IDirectDraw2Impl_EnumSurfaces,
-    IDirectDraw2Impl_FlipToGDISurface,
-    Xlib_IDirectDraw2Impl_GetCaps,
-    IDirectDraw2Impl_GetDisplayMode,
-    Xlib_IDirectDraw2Impl_GetFourCCCodes,
-    IDirectDraw2Impl_GetGDISurface,
-    IDirectDraw2Impl_GetMonitorFrequency,
-    IDirectDraw2Impl_GetScanLine,
-    IDirectDraw2Impl_GetVerticalBlankStatus,
-    IDirectDraw2Impl_Initialize,
-    IDirectDraw2Impl_RestoreDisplayMode,
-    Xlib_IDirectDraw2Impl_SetCooperativeLevel,
-    Xlib_IDirectDraw2Impl_SetDisplayMode,
-    IDirectDraw2Impl_WaitForVerticalBlank,
-    Xlib_IDirectDraw2Impl_GetAvailableVidMem	
-};
-
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)	(typeof(xlib_dd4vt.fn##fun))
-#else
-# define XCAST(fun)	(void*)
-#endif
-
-ICOM_VTABLE(IDirectDraw4) xlib_dd4vt = {
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
-    XCAST(AddRef)IDirectDraw2Impl_AddRef,
-    XCAST(Release)Xlib_IDirectDraw2Impl_Release,
-    XCAST(Compact)IDirectDraw2Impl_Compact,
-    XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
-    XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
-    XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
-    XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
-    XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
-    XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
-    XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
-    XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
-    XCAST(GetDisplayMode)IDirectDraw2Impl_GetDisplayMode,
-    XCAST(GetFourCCCodes)Xlib_IDirectDraw2Impl_GetFourCCCodes,
-    XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
-    XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
-    XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
-    XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
-    XCAST(Initialize)IDirectDraw2Impl_Initialize,
-    XCAST(RestoreDisplayMode)IDirectDraw2Impl_RestoreDisplayMode,
-    XCAST(SetCooperativeLevel)Xlib_IDirectDraw2Impl_SetCooperativeLevel,
-    XCAST(SetDisplayMode)Xlib_IDirectDraw2Impl_SetDisplayMode,
-    XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
-    XCAST(GetAvailableVidMem)Xlib_IDirectDraw2Impl_GetAvailableVidMem,
-    IDirectDraw4Impl_GetSurfaceFromDC,
-    IDirectDraw4Impl_RestoreAllSurfaces,
-    IDirectDraw4Impl_TestCooperativeLevel,
-    IDirectDraw4Impl_GetDeviceIdentifier
-};
-#undef XCAST
-
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)	(typeof(xlib_dd7vt.fn##fun))
-#else
-# define XCAST(fun)	(void*)
-#endif
-
-ICOM_VTABLE(IDirectDraw7) xlib_dd7vt = {
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
-    XCAST(AddRef)IDirectDraw2Impl_AddRef,
-    XCAST(Release)Xlib_IDirectDraw2Impl_Release,
-    XCAST(Compact)IDirectDraw2Impl_Compact,
-    XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
-    XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
-    XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
-    XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
-    XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
-    XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
-    XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
-    XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
-    XCAST(GetDisplayMode)IDirectDraw2Impl_GetDisplayMode,
-    XCAST(GetFourCCCodes)Xlib_IDirectDraw2Impl_GetFourCCCodes,
-    XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
-    XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
-    XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
-    XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
-    XCAST(Initialize)IDirectDraw2Impl_Initialize,
-    XCAST(RestoreDisplayMode)IDirectDraw2Impl_RestoreDisplayMode,
-    XCAST(SetCooperativeLevel)Xlib_IDirectDraw2Impl_SetCooperativeLevel,
-    XCAST(SetDisplayMode)Xlib_IDirectDraw2Impl_SetDisplayMode,
-    XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
-    XCAST(GetAvailableVidMem)Xlib_IDirectDraw2Impl_GetAvailableVidMem,
-    XCAST(GetSurfaceFromDC)IDirectDraw4Impl_GetSurfaceFromDC,
-    XCAST(RestoreAllSurfaces)IDirectDraw4Impl_RestoreAllSurfaces,
-    XCAST(TestCooperativeLevel)IDirectDraw4Impl_TestCooperativeLevel,
-    XCAST(GetDeviceIdentifier)IDirectDraw4Impl_GetDeviceIdentifier,
-    IDirectDraw7Impl_StartModeTest,
-    IDirectDraw7Impl_EvaluateMode,
-};
-#undef XCAST
diff --git a/dlls/ddraw/ddraw/xvidmode.c b/dlls/ddraw/ddraw/xvidmode.c
new file mode 100644
index 0000000..502df50
--- /dev/null
+++ b/dlls/ddraw/ddraw/xvidmode.c
@@ -0,0 +1,387 @@
+/*	DirectDraw driver for User-based primary surfaces
+ *	with XF86VidMode mode switching in full-screen mode.
+ *
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_LIBXXF86VM
+
+#include "debugtools.h"
+#include "ts_xlib.h"
+#include "ts_xf86vmode.h"
+#include "x11drv.h"
+#include <ddraw.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "ddraw_private.h"
+#include "ddraw/main.h"
+#include "ddraw/user.h"
+#include "ddraw/xvidmode.h"
+#include "dclipper/main.h"
+#include "dpalette/main.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/user.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static ICOM_VTABLE(IDirectDraw7) XVidMode_DirectDraw_VTable;
+
+static const DDDEVICEIDENTIFIER2 xvidmode_device = 
+{
+    "User/XF86VidMode Driver",
+    "WINE DirectDraw on User with XF86VidMode",
+    { { 0x00010001, 0x00010001 } },
+    0, 0, 0, 0,
+    /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
+    {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
+    0
+};
+
+HRESULT XVidMode_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+				   IUnknown* pUnkOuter, BOOL ex);
+HRESULT XVidMode_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
+
+static const ddraw_driver xvidmode_driver =
+{
+    &xvidmode_device,
+    11, /* User is 10 */
+    XVidMode_DirectDraw_Create,
+    XVidMode_DirectDraw_Initialize
+};
+
+static XF86VidModeModeInfo** modes;
+static DWORD num_modes;
+
+/* Called from DllInit, which is synchronised so there are no threading
+ * concerns. */
+static BOOL initialize(void)
+{
+    int nmodes;
+    int major, minor;
+
+    if (X11DRV_GetXRootWindow() != DefaultRootWindow(display)) return FALSE;
+
+    if (!TSXF86VidModeQueryVersion(display, &major, &minor)) return FALSE;
+
+    if (!TSXF86VidModeGetAllModeLines(display, DefaultScreen(display), &nmodes,
+				      &modes))
+	return FALSE;
+
+    num_modes = nmodes;
+
+    TRACE("enabling XVidMode\n");
+
+    return TRUE;
+}
+
+static void cleanup(void)
+{
+    TSXFree(modes);
+}
+
+static HRESULT set_display_mode(XF86VidModeModeInfo* mode)
+{
+    int screen = DefaultScreen(display);
+
+    TRACE("%d %d\n", mode->hdisplay, mode->vdisplay);
+
+    /* This is questionable. Programs should leave switching unlocked when
+     * they exit. So the only reason the display should be locked is if
+     * another really doesn't want switches to happen. Maybe it would be better
+     * to detect an XF86VideModeZoomLocked error. */
+    TSXF86VidModeLockModeSwitch(display, screen, False);
+
+    TSXSync(display, False);
+
+    TSXF86VidModeSwitchToMode(display, screen, mode);
+
+    TSXSync(display, False);
+
+#if 0 /* doesn't work for me */
+    TSXF86VidModeSetViewPort(display, screen, 0, 0);
+#else
+    TSXWarpPointer(display, None, RootWindow(display, screen), 0, 0, 0, 0, 0,
+		   0);
+#endif
+
+    TSXFlush(display);
+
+    return S_OK;
+}
+
+static XF86VidModeModeInfo* choose_mode(DWORD dwWidth, DWORD dwHeight,
+					DWORD dwRefreshRate, DWORD dwFlags)
+{
+    XF86VidModeModeInfo* best = NULL;
+    int i;
+
+    /* Choose the smallest mode that is large enough. */
+    for (i=0; i < num_modes; i++)
+    {
+	if (modes[i]->hdisplay >= dwWidth && modes[i]->vdisplay >= dwHeight)
+	{
+	    if (best == NULL) best = modes[i];
+	    else
+	    {
+		if (modes[i]->hdisplay < best->hdisplay
+		    || modes[i]->vdisplay < best->vdisplay)
+		    best = modes[i];
+	    }
+	}
+    }
+
+    /* all modes were too small, use the largest */
+    if (best == NULL)
+    {
+	TRACE("all modes too small\n");
+
+	for (i=1; i < num_modes; i++)
+	{
+	    if (best == NULL) best = modes[i];
+	    else
+	    {
+		if (modes[i]->hdisplay > best->hdisplay
+		    || modes[i]->vdisplay > best->vdisplay)
+		    best = modes[i];
+	    }
+	}
+    }
+
+    TRACE("using %d %d for %lu %lu\n", best->hdisplay, best->vdisplay,
+	  dwWidth, dwHeight);
+
+    return best;
+}
+
+static XF86VidModeModeInfo* get_current_mode(void)
+{
+    XF86VidModeModeLine line;
+    int dotclock;
+    int i;
+
+    TSXF86VidModeGetModeLine(display, DefaultScreen(display), &dotclock,
+			     &line);
+
+    for (i=0; i < num_modes; i++)
+    {
+	if (modes[i]->dotclock == dotclock
+	    && modes[i]->hdisplay == line.hdisplay
+	    && modes[i]->hsyncstart == line.hsyncstart
+	    && modes[i]->hsyncend == line.hsyncend
+	    && modes[i]->htotal == line.htotal
+	    /* && modes[i]->hskew == line.hskew */
+	    && modes[i]->vdisplay == line.vdisplay
+	    && modes[i]->vsyncstart == line.vsyncstart
+	    && modes[i]->vsyncend == line.vsyncend
+	    && modes[i]->vtotal == line.vtotal
+	    && modes[i]->flags == line.flags)
+	    return modes[i];
+    }
+
+    WARN("this can't happen\n");
+    return modes[0]; /* should be the mode that X started in */
+}
+
+BOOL DDRAW_XVidMode_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    if (fdwReason == DLL_PROCESS_ATTACH)
+    {
+	if (initialize())
+	    DDRAW_register_driver(&xvidmode_driver);
+    }
+    else if (fdwReason == DLL_PROCESS_DETACH)
+    {
+	cleanup();
+    }
+
+    return TRUE;
+}
+
+/* Not called from the vtable. */
+HRESULT XVidMode_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
+{
+    XVIDMODE_DDRAW_PRIV_VAR(priv,This);
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = User_DirectDraw_Construct(This, ex);
+    if (FAILED(hr)) return hr;
+
+    This->final_release = XVidMode_DirectDraw_final_release;
+
+    priv->xvidmode.original_mode = get_current_mode();
+    priv->xvidmode.current_mode = priv->xvidmode.original_mode;
+
+    ICOM_INIT_INTERFACE(This, IDirectDraw7, XVidMode_DirectDraw_VTable);
+
+    return S_OK;
+}
+
+/* This function is called from DirectDrawCreate(Ex) on the most-derived
+ * class to start construction.
+ * Not called from the vtable. */
+HRESULT XVidMode_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+				   IUnknown* pUnkOuter, BOOL ex)
+{
+    HRESULT hr;
+    IDirectDrawImpl* This;
+
+    TRACE("\n");
+
+    assert(pUnkOuter == NULL);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(IDirectDrawImpl)
+		     + sizeof(XVidMode_DirectDrawImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    /* Note that this relation does *not* hold true if the DD object was
+     * CoCreateInstanced then Initialized. */
+    This->private = (XVidMode_DirectDrawImpl *)(This+1);
+
+    hr = XVidMode_DirectDraw_Construct(This, ex);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*pIface = ICOM_INTERFACE(This, IDirectDraw7);
+
+    return hr;
+}
+
+/* This function is called from Uninit_DirectDraw_Initialize on the
+ * most-derived-class to start initialization.
+ * Not called from the vtable. */
+HRESULT XVidMode_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
+{
+    HRESULT hr;
+
+    TRACE("\n");
+
+    This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+			      sizeof(XVidMode_DirectDrawImpl));
+    if (This->private == NULL) return E_OUTOFMEMORY;
+
+    hr = XVidMode_DirectDraw_Construct(This, TRUE); /* XXX ex? */
+    if (FAILED(hr))
+    {
+	HeapFree(GetProcessHeap(), 0, This->private);
+	return hr;
+    }
+
+    return DD_OK;
+}
+
+/* Called from an internal function pointer. */
+void XVidMode_DirectDraw_final_release(IDirectDrawImpl *This)
+{
+    XVIDMODE_DDRAW_PRIV_VAR(priv, This);
+
+    if (priv->xvidmode.current_mode != priv->xvidmode.original_mode)
+	set_display_mode(priv->xvidmode.original_mode);
+
+    User_DirectDraw_final_release(This);
+}
+
+HRESULT WINAPI
+XVidMode_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+					LPDDDEVICEIDENTIFIER2 pDDDI,
+					DWORD dwFlags)
+{
+    *pDDDI = xvidmode_device;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+XVidMode_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
+{
+    ICOM_THIS(IDirectDrawImpl, iface);
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = Main_DirectDraw_RestoreDisplayMode(iface);
+    if (SUCCEEDED(hr))
+    {
+	XVIDMODE_DDRAW_PRIV_VAR(priv, This);
+
+	if (priv->xvidmode.current_mode != priv->xvidmode.original_mode)
+	{
+	    set_display_mode(priv->xvidmode.original_mode);
+	    priv->xvidmode.current_mode = priv->xvidmode.original_mode;
+	}
+    }
+
+    return hr;
+}
+
+HRESULT WINAPI
+XVidMode_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+				   DWORD dwHeight, DWORD dwBPP,
+				   DWORD dwRefreshRate, DWORD dwFlags)
+{
+    ICOM_THIS(IDirectDrawImpl, iface);
+
+    HRESULT hr;
+
+    TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
+    hr = User_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP,
+					dwRefreshRate, dwFlags);
+
+    if (SUCCEEDED(hr))
+    {
+	XVIDMODE_DDRAW_PRIV_VAR(priv, This);
+	XF86VidModeModeInfo* new_mode;
+
+	new_mode = choose_mode(dwWidth, dwHeight, dwRefreshRate, dwFlags);
+
+	if (new_mode != NULL && new_mode != priv->xvidmode.current_mode)
+	{
+	    priv->xvidmode.current_mode = new_mode;
+	    set_display_mode(priv->xvidmode.current_mode);
+	}
+    }
+
+    return hr;
+}
+
+static ICOM_VTABLE(IDirectDraw7) XVidMode_DirectDraw_VTable =
+{
+    Main_DirectDraw_QueryInterface,
+    Main_DirectDraw_AddRef,
+    Main_DirectDraw_Release,
+    Main_DirectDraw_Compact,
+    Main_DirectDraw_CreateClipper,
+    Main_DirectDraw_CreatePalette,
+    Main_DirectDraw_CreateSurface,
+    Main_DirectDraw_DuplicateSurface,
+    User_DirectDraw_EnumDisplayModes,
+    Main_DirectDraw_EnumSurfaces,
+    Main_DirectDraw_FlipToGDISurface,
+    User_DirectDraw_GetCaps,
+    Main_DirectDraw_GetDisplayMode,
+    Main_DirectDraw_GetFourCCCodes,
+    Main_DirectDraw_GetGDISurface,
+    Main_DirectDraw_GetMonitorFrequency,
+    Main_DirectDraw_GetScanLine,
+    Main_DirectDraw_GetVerticalBlankStatus,
+    Main_DirectDraw_Initialize,
+    XVidMode_DirectDraw_RestoreDisplayMode,
+    Main_DirectDraw_SetCooperativeLevel,
+    XVidMode_DirectDraw_SetDisplayMode,
+    Main_DirectDraw_WaitForVerticalBlank,
+    Main_DirectDraw_GetAvailableVidMem,
+    Main_DirectDraw_GetSurfaceFromDC,
+    Main_DirectDraw_RestoreAllSurfaces,
+    Main_DirectDraw_TestCooperativeLevel,
+    XVidMode_DirectDraw_GetDeviceIdentifier,
+    Main_DirectDraw_StartModeTest,
+    Main_DirectDraw_EvaluateMode
+};
+
+#endif /* HAVE_LIBXXF86VM */
diff --git a/dlls/ddraw/ddraw/xvidmode.h b/dlls/ddraw/ddraw/xvidmode.h
new file mode 100644
index 0000000..8ba0b18
--- /dev/null
+++ b/dlls/ddraw/ddraw/xvidmode.h
@@ -0,0 +1,39 @@
+/* Copyright 2000 TransGaming Technologies, Inc. */
+#ifndef WINE_DDRAW_DDRAW_XVIDMODE_H_INCLUDED
+#define WINE_DDRAW_DDRAW_XVIDMODE_H_INCLUDED
+
+#include <X11/extensions/xf86vmode.h>
+
+#define XVIDMODE_DDRAW_PRIV(ddraw) \
+	((XVidMode_DirectDrawImpl*)((ddraw)->private))
+#define XVIDMODE_DDRAW_PRIV_VAR(name,ddraw) \
+	XVidMode_DirectDrawImpl* name = XVIDMODE_DDRAW_PRIV(ddraw)
+
+typedef struct
+{
+    XF86VidModeModeInfo* original_mode;
+    XF86VidModeModeInfo* current_mode;
+} XVidMode_DirectDrawImpl_Part;
+
+typedef struct
+{
+    User_DirectDrawImpl_Part user;
+    XVidMode_DirectDrawImpl_Part xvidmode;
+} XVidMode_DirectDrawImpl;
+
+void XVidMode_DirectDraw_final_release(IDirectDrawImpl* This);
+HRESULT XVidMode_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex);
+HRESULT XVidMode_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+				   IUnknown* pUnkOuter, BOOL ex);
+HRESULT WINAPI
+XVidMode_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+					LPDDDEVICEIDENTIFIER2 pDDDI,
+					DWORD dwFlags);
+HRESULT WINAPI
+XVidMode_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+				   DWORD dwHeight, DWORD dwBPP,
+				   DWORD dwRefreshRate, DWORD dwFlags);
+HRESULT WINAPI
+XVidMode_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface);
+
+#endif
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 803a4b5..20617fc 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -1,3 +1,5 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
 #ifndef __WINE_DLLS_DDRAW_DDRAW_PRIVATE_H
 #define __WINE_DLLS_DDRAW_DDRAW_PRIVATE_H
 
@@ -8,223 +10,146 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "ddraw.h"
+#include "ddcomimpl.h"
 
-static const char WINE_UNUSED *ddProp = "WINE_DDRAW_Property";
-
-/****************************************************************************
- * This is the main DirectDraw driver interface. It is supposed to be called
- * only from the base functions and only used by those. It should neither be
- * be called nor used within the interfaces.
- */
-typedef struct ddraw_driver {
-	LPGUID	guid;		/*under which we are referenced and enumerated*/
-	CHAR	type[20];	/* type, usually "display" */
-	CHAR	name[40];	/* name, like "WINE Foobar DirectDraw Driver" */
-	int	preference;	/* how good we are. dga might get 100, xlib 50*/
-	HRESULT	(*createDDRAW)(LPDIRECTDRAW*); /* also check if arg is NULL */
-} ddraw_driver;
-
-extern void ddraw_register_driver(ddraw_driver*);
-
-/*****************************************************************************
- * The implementation structures. They must not contain driver specific stuff.
- * 
- * For private data the "LPVOID private" pointer should be used.
- */
-
-typedef struct IDirectDrawImpl	IDirectDrawImpl;
-typedef struct IDirectDraw2Impl	IDirectDraw2Impl;
-typedef struct IDirectDraw3Impl	IDirectDraw3Impl;
-typedef struct IDirectDraw4Impl	IDirectDraw4Impl;
-typedef struct IDirectDrawPaletteImpl	IDirectDrawPaletteImpl;
-typedef struct IDirectDrawClipperImpl	IDirectDrawClipperImpl;
-
-typedef struct IDirectDrawSurfaceImpl IDirectDrawSurfaceImpl;
-typedef struct IDirectDrawSurface2Impl IDirectDrawSurface2Impl;
-typedef struct IDirectDrawSurface4Impl IDirectDrawSurface4Impl;
-
-
-extern struct ICOM_VTABLE(IDirectDrawClipper)	ddclipvt;
-extern struct ICOM_VTABLE(IDirectDrawPalette)	ddraw_ddpalvt;
+/* XXX Put this somewhere proper. */
+#define DD_STRUCT_INIT(x)			\
+	do {					\
+		memset((x), 0, sizeof(*(x)));	\
+		(x)->dwSize = sizeof(*x);	\
+	} while (0)
 
 /*****************************************************************************
  * IDirectDraw implementation structure
  */
-struct _common_directdrawdata
+
+typedef struct IDirectDrawImpl IDirectDrawImpl;
+typedef struct IDirectDrawPaletteImpl IDirectDrawPaletteImpl;
+typedef struct IDirectDrawClipperImpl IDirectDrawClipperImpl;
+typedef struct IDirectDrawSurfaceImpl IDirectDrawSurfaceImpl;
+
+typedef void (*pixel_convert_func)(void *src, void *dst, DWORD width,
+				   DWORD height, LONG pitch,
+				   IDirectDrawPaletteImpl *palette);
+
+typedef void (*palette_convert_func)(LPPALETTEENTRY palent,
+				     void *screen_palette, DWORD start,
+				     DWORD count);
+
+struct IDirectDrawImpl
 {
-    int		  ref;		/* for this structure, only once per obj */
-    DDPIXELFORMAT directdraw_pixelformat;
+    ICOM_VFIELD_MULTI(IDirectDraw7);
+    ICOM_VFIELD_MULTI(IDirectDraw4);
+    ICOM_VFIELD_MULTI(IDirectDraw2);
+    ICOM_VFIELD_MULTI(IDirectDraw);
+
+    DWORD ref;
+
+    /* TRUE if created via DirectDrawCreateEx or CoCreateInstance,
+     * FALSE if created via DirectDrawCreate. */
+    BOOL ex;
+
+    /* Linked list of surfaces, joined by next_ddraw in IDirectSurfaceImpl. */
+    IDirectDrawSurfaceImpl* surfaces;
+    /* Linked list of palettes, joined by next_ddraw. */
+    IDirectDrawPaletteImpl* palettes;
+    /* Linked list of clippers, joined by next_ddraw. */
+    IDirectDrawClipperImpl* clippers;
+
+    IDirectDrawSurfaceImpl* primary_surface;
+
+    HWND window;
+    DWORD cooperative_level;
+    WNDPROC original_wndproc;
+
+    DWORD width, height;
+    LONG pitch;
+    DDPIXELFORMAT pixelformat;
+
+    /* Should each of these go into some structure? */
+    DWORD orig_width, orig_height;
+    LONG orig_pitch;
+    DDPIXELFORMAT orig_pixelformat;
+
+    /* Called when the refcount goes to 0. */
+    void (*final_release)(IDirectDrawImpl *This);
+
+    HRESULT (*create_palette)(IDirectDrawImpl* This, DWORD dwFlags,
+			      LPDIRECTDRAWPALETTE* ppPalette,
+			      LPUNKNOWN pUnkOuter);
+
+    /* Surface creation functions. For all of these, pOuter == NULL. */
+
+    /* Do not create any backbuffers or the flipping chain. */
+    HRESULT (*create_primary)(IDirectDrawImpl* This,
+			      const DDSURFACEDESC2* pDDSD,
+			      LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter);
+
+    /* Primary may be NULL if we are creating an unattached backbuffer. */
+    HRESULT (*create_backbuffer)(IDirectDrawImpl* This,
+				 const DDSURFACEDESC2* pDDSD,
+				 LPDIRECTDRAWSURFACE7* ppSurf,
+				 LPUNKNOWN pOuter,
+				 IDirectDrawSurfaceImpl* primary);
+
+    /* shiny happy offscreenplain surfaces */
+    HRESULT (*create_offscreen)(IDirectDrawImpl* This,
+				const DDSURFACEDESC2* pDDSD,
+				LPDIRECTDRAWSURFACE7* ppSurf,
+				LPUNKNOWN pOuter);
+
+    /* dwMipMapLevel is specified as per OpenGL. (i.e. 0 is base) */
+    HRESULT (*create_texture)(IDirectDrawImpl* This,
+			      const DDSURFACEDESC2* pDDSD,
+			      LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter,
+			      DWORD dwMipMapLevel);
+
+    HRESULT (*create_zbuffer)(IDirectDrawImpl* This,
+			      const DDSURFACEDESC2* pDDSD,
+			      LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter);
+    
+    LPVOID	private;
+
+    /* Everything below here is still questionable. */
+
     DDPIXELFORMAT screen_pixelformat;
 
     int           pixmap_depth;
-    void (*pixel_convert)(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl *palette);
-    void (*palette_convert)(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count);
-    DWORD         height,width;	/* set by SetDisplayMode */
-    HWND          mainWindow;   /* set by SetCooperativeLevel */
+    pixel_convert_func pixel_convert;
+    palette_convert_func palette_convert;
+    const struct tagDC_FUNCS *funcs, *old_funcs; /* DISPLAY.DRV overrides */
 
     /* This is for the fake mainWindow */
-    ATOM          winclass;
-    HWND          window;
-    PAINTSTRUCT   ps;
-    int           paintable;
-    LPVOID	  private;
+    ATOM	winclass;
+    PAINTSTRUCT	ps;
+    BOOL	paintable;
 };
 
 /*****************************************************************************
- * IDirectDraw implementation structure
- * 
- * Note: All the IDirectDraw*Impl structures _MUST_ have IDENTICAL layout,
- * 	 since we reuse functions across interface versions.
- */
-struct IDirectDrawImpl
-{
-    /* IUnknown fields */
-    ICOM_VFIELD(IDirectDraw);
-    DWORD				ref;
-
-    /* IDirectDraw fields */
-    struct _common_directdrawdata	*d;
-};
-
-struct IDirectDraw2Impl
-{
-    /* IUnknown fields */
-    ICOM_VFIELD(IDirectDraw2);
-    DWORD				ref;
-
-    /* IDirectDraw fields */
-    struct _common_directdrawdata	*d;
-};
-
-extern HRESULT WINAPI IDirectDrawImpl_SetDisplayMode(
-	LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
-);
-
-extern HRESULT WINAPI IDirectDraw2Impl_DuplicateSurface(
-	LPDIRECTDRAW2 iface,LPDIRECTDRAWSURFACE src,LPDIRECTDRAWSURFACE *dst
-);
-extern HRESULT WINAPI IDirectDraw2Impl_SetCooperativeLevel(
-	LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel
-);
-extern HRESULT WINAPI IDirectDraw2Impl_GetCaps(
-	LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
-) ;
-extern HRESULT WINAPI IDirectDraw2Impl_CreateClipper(
-    LPDIRECTDRAW2 iface,DWORD x,LPDIRECTDRAWCLIPPER *lpddclip,LPUNKNOWN lpunk
-);
-extern HRESULT WINAPI common_IDirectDraw2Impl_CreatePalette(
-    IDirectDraw2Impl* This,DWORD dwFlags,LPPALETTEENTRY palent,
-    IDirectDrawPaletteImpl **lpddpal,LPUNKNOWN lpunk,int *psize
-);
-extern HRESULT WINAPI IDirectDraw2Impl_CreatePalette(
-    LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
-);
-extern HRESULT WINAPI IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface);
-extern HRESULT WINAPI IDirectDraw2Impl_WaitForVerticalBlank(
-	LPDIRECTDRAW2 iface,DWORD x,HANDLE h
-);
-extern ULONG WINAPI IDirectDraw2Impl_AddRef(LPDIRECTDRAW2 iface);
-extern ULONG WINAPI IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface);
-extern HRESULT WINAPI IDirectDraw2Impl_QueryInterface(
-	LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
-);
-extern HRESULT WINAPI IDirectDraw2Impl_GetVerticalBlankStatus(
-	LPDIRECTDRAW2 iface,BOOL *status
-);
-extern HRESULT WINAPI IDirectDraw2Impl_EnumDisplayModes(
-	LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
-);
-extern HRESULT WINAPI IDirectDraw2Impl_GetDisplayMode(
-	LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
-);
-extern HRESULT WINAPI IDirectDraw2Impl_FlipToGDISurface(LPDIRECTDRAW2 iface);
-extern HRESULT WINAPI IDirectDraw2Impl_GetMonitorFrequency(
-    LPDIRECTDRAW2 iface,LPDWORD freq
-);
-extern HRESULT WINAPI IDirectDraw2Impl_GetFourCCCodes(
-    LPDIRECTDRAW2 iface,LPDWORD x,LPDWORD y
-);
-extern HRESULT WINAPI IDirectDraw2Impl_EnumSurfaces(
-    LPDIRECTDRAW2 iface,DWORD x,LPDDSURFACEDESC ddsfd,LPVOID context,
-    LPDDENUMSURFACESCALLBACK ddsfcb
-);
-extern HRESULT WINAPI IDirectDraw2Impl_Compact( LPDIRECTDRAW2 iface );
-extern HRESULT WINAPI IDirectDraw2Impl_GetGDISurface(
-    LPDIRECTDRAW2 iface, LPDIRECTDRAWSURFACE *lplpGDIDDSSurface
-);
-extern HRESULT WINAPI IDirectDraw2Impl_GetScanLine(
-    LPDIRECTDRAW2 iface, LPDWORD lpdwScanLine
-);
-extern HRESULT WINAPI IDirectDraw2Impl_Initialize(LPDIRECTDRAW2 iface, GUID *lpGUID);
-extern HRESULT WINAPI IDirectDraw2Impl_SetDisplayMode(
-    LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,
-    DWORD dwRefreshRate, DWORD dwFlags
-);
-extern HRESULT WINAPI IDirectDraw2Impl_GetAvailableVidMem(
-	LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
-);
-extern HRESULT common_off_screen_CreateSurface(
-	IDirectDraw2Impl* This,IDirectDrawSurfaceImpl* lpdsf
-);
-
-/*
- * IDirectDraw4 implementation structure
- */
-struct IDirectDraw4Impl
-{
-    /* IUnknown fields */
-    ICOM_VFIELD(IDirectDraw4);
-    DWORD				ref;
-    /* IDirectDraw4 fields */
-    struct _common_directdrawdata	*d;
-};
-
-extern HRESULT WINAPI IDirectDraw4Impl_GetSurfaceFromDC(
-	LPDIRECTDRAW4 iface, HDC hdc, LPDIRECTDRAWSURFACE *lpDDS
-);
-extern HRESULT WINAPI IDirectDraw4Impl_RestoreAllSurfaces(LPDIRECTDRAW4 iface);
-extern HRESULT WINAPI IDirectDraw4Impl_TestCooperativeLevel(LPDIRECTDRAW4 iface);
-extern HRESULT WINAPI IDirectDraw4Impl_GetDeviceIdentifier(LPDIRECTDRAW4 iface,
-						    LPDDDEVICEIDENTIFIER lpdddi,
-						    DWORD dwFlags
-);
-
-extern HRESULT WINAPI IDirectDraw7Impl_StartModeTest(
-	LPDIRECTDRAW7 iface,LPSIZE modetotest,DWORD num,DWORD flags
-);
-extern HRESULT WINAPI IDirectDraw7Impl_EvaluateMode(
-	LPDIRECTDRAW7 iface,DWORD flags,DWORD *seconduntiltimeout
-);
-
-/*****************************************************************************
  * IDirectDrawPalette implementation structure
  */
 struct IDirectDrawPaletteImpl
 {
     /* IUnknown fields */
-    ICOM_VFIELD(IDirectDrawPalette);
-    DWORD		ref;
+    ICOM_VFIELD_MULTI(IDirectDrawPalette);
+    DWORD ref;
 
     /* IDirectDrawPalette fields */
-    IDirectDrawImpl*		ddraw;	/* direct draw, no reference count */
+    DWORD		flags;
+    HPALETTE		hpal;
+    WORD		palVersion, palNumEntries; /* LOGPALETTE */
     PALETTEENTRY	palents[256];
-
     /* This is to store the palette in 'screen format' */
     int			screen_palents[256];
+
+    VOID (*final_release)(IDirectDrawPaletteImpl* This);
+
+    IDirectDrawImpl* ddraw_owner;
+    IDirectDrawPaletteImpl* prev_ddraw;
+    IDirectDrawPaletteImpl* next_ddraw;
+
     LPVOID		private;
 };
-extern HRESULT WINAPI IDirectDrawPaletteImpl_GetEntries(LPDIRECTDRAWPALETTE,DWORD,DWORD,DWORD,LPPALETTEENTRY);
-extern HRESULT WINAPI IDirectDrawPaletteImpl_SetEntries(LPDIRECTDRAWPALETTE,DWORD,DWORD,DWORD,LPPALETTEENTRY);
-extern ULONG WINAPI IDirectDrawPaletteImpl_Release(LPDIRECTDRAWPALETTE);
-extern ULONG WINAPI IDirectDrawPaletteImpl_AddRef(LPDIRECTDRAWPALETTE);
-extern HRESULT WINAPI IDirectDrawPaletteImpl_Initialize(LPDIRECTDRAWPALETTE,LPDIRECTDRAW,DWORD,LPPALETTEENTRY);
-extern HRESULT WINAPI IDirectDrawPaletteImpl_GetCaps(LPDIRECTDRAWPALETTE,LPDWORD);
-extern HRESULT WINAPI IDirectDrawPaletteImpl_QueryInterface(LPDIRECTDRAWPALETTE,REFIID,LPVOID *);
-
-extern HRESULT WINAPI common_IDirectDraw2Impl_CreatePalette(
-    IDirectDraw2Impl* This,DWORD dwFlags,LPPALETTEENTRY palent,
-    IDirectDrawPaletteImpl **lpddpal,LPUNKNOWN lpunk,int *psize
-);
 
 /*****************************************************************************
  * IDirectDrawClipper implementation structure
@@ -232,145 +157,114 @@
 struct IDirectDrawClipperImpl
 {
     /* IUnknown fields */
-    ICOM_VFIELD(IDirectDrawClipper);
-    DWORD                            ref;
+    ICOM_VFIELD_MULTI(IDirectDrawClipper);
+    DWORD ref;
 
     /* IDirectDrawClipper fields */
     HWND hWnd;
+
+    IDirectDrawImpl* ddraw_owner;
+    IDirectDrawClipperImpl* prev_ddraw;
+    IDirectDrawClipperImpl* next_ddraw;
 };
 
 /*****************************************************************************
  * IDirectDrawSurface implementation structure
  */
-struct IDirect3DTexture2Impl;
-struct _common_directdrawsurface
-{
-    IDirectDrawPaletteImpl*     palette;
-    IDirectDraw2Impl*           ddraw;
-
-    struct _surface_chain 	*chain;
-
-    DDSURFACEDESC               surface_desc;
-
-    /* For Get / Release DC methods */
-    HBITMAP			DIBsection;
-    void			*bitmap_data;
-    HDC				hdc;
-    HGDIOBJ			holdbitmap;
-    LPDIRECTDRAWCLIPPER		lpClipper;
-    
-    /* Callback for loaded textures */
-    struct IDirect3DTexture2Impl*	texture;
-    HRESULT WINAPI		(*SetColorKey_cb)(struct IDirect3DTexture2Impl *texture, DWORD dwFlags, LPDDCOLORKEY ckey ) ; 
-};
-extern IDirectDrawSurface4Impl* _common_find_flipto(IDirectDrawSurface4Impl* This,IDirectDrawSurface4Impl* flipto);
 
 struct IDirectDrawSurfaceImpl
 {
     /* IUnknown fields */
-    ICOM_VFIELD(IDirectDrawSurface);
-    DWORD                            ref;
+    ICOM_VFIELD_MULTI(IDirectDrawSurface7);
+    ICOM_VFIELD_MULTI(IDirectDrawSurface3);
+    DWORD ref;
 
-    /* IDirectDrawSurface fields */
-    struct _common_directdrawsurface	s;
+    struct IDirectDrawSurfaceImpl* attached; /* attached surfaces */
+
+    struct IDirectDrawSurfaceImpl* next_ddraw; /* ddraw surface chain */
+    struct IDirectDrawSurfaceImpl* prev_ddraw;
+    struct IDirectDrawSurfaceImpl* next_attached; /* attached surface chain */
+    struct IDirectDrawSurfaceImpl* prev_attached;
+
+    IDirectDrawImpl* ddraw_owner;
+    IDirectDrawSurfaceImpl* surface_owner;
+
+    IDirectDrawPaletteImpl* palette; /* strong ref */
+    IDirectDrawClipperImpl* clipper; /* strong ref */
+
+    DDSURFACEDESC2 surface_desc;
+
+    HDC hDC;
+    BOOL dc_in_use;
+
+    HRESULT (*duplicate_surface)(IDirectDrawSurfaceImpl* src,
+				 LPDIRECTDRAWSURFACE7* dst);
+    void (*final_release)(IDirectDrawSurfaceImpl *This);
+    BOOL (*attach)(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *to);
+    BOOL (*detach)(IDirectDrawSurfaceImpl *This);
+    void (*lock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect);
+    void (*unlock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect);
+    void (*lose_surface)(IDirectDrawSurfaceImpl* This);
+    void (*flip_data)(IDirectDrawSurfaceImpl* front,
+		      IDirectDrawSurfaceImpl* back);
+    void (*flip_update)(IDirectDrawSurfaceImpl* front);
+    HRESULT (*get_dc)(IDirectDrawSurfaceImpl* This, HDC* phDC);
+    HRESULT (*release_dc)(IDirectDrawSurfaceImpl* This, HDC hDC);
+    void (*set_palette)(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* pal);
+    void (*update_palette)(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* pal,
+			   DWORD dwStart, DWORD dwCount, LPPALETTEENTRY palent);
+    HWND (*get_display_window)(IDirectDrawSurfaceImpl *This);
+
+    struct PrivateData* private_data;
+
+    DWORD max_lod;
+    DWORD priority;
+
+    BOOL lost;
+
+    DWORD uniqueness_value;
+
     LPVOID private;
+
+    /* Everything below here is dodgy. */
+    /* For Direct3D use */
+    LPVOID			aux_ctx, aux_data;
+    void (*aux_release)(LPVOID ctx, LPVOID data);
+    BOOL (*aux_flip)(LPVOID ctx, LPVOID data);
+    void (*aux_unlock)(LPVOID ctx, LPVOID data, LPRECT lpRect);
+    struct IDirect3DTexture2Impl*	texture;
+    HRESULT WINAPI		(*SetColorKey_cb)(struct IDirect3DTexture2Impl *texture, DWORD dwFlags, LPDDCOLORKEY ckey ) ; 
 };
 
 /*****************************************************************************
- * IDirectDrawSurface2 implementation structure
+ * Driver initialisation functions.
  */
-struct IDirectDrawSurface2Impl
-{
-    /* IUnknown fields */
-    ICOM_VFIELD(IDirectDrawSurface2);
-    DWORD                             ref;
-    /* IDirectDrawSurface2 fields */
-    struct _common_directdrawsurface	s;
-    LPVOID private;
-};
+BOOL DDRAW_User_Init(HINSTANCE, DWORD, LPVOID);
 
-/*****************************************************************************
- * IDirectDrawSurface3 implementation structure
+typedef struct {
+    const DDDEVICEIDENTIFIER2* info;
+    int	preference;	/* how good we are. dga might get 100, xlib 50*/
+    HRESULT (*create)(const GUID*, LPDIRECTDRAW7*, LPUNKNOWN, BOOL ex);
+
+    /* For IDirectDraw7::Initialize. */
+    HRESULT (*init)(IDirectDrawImpl *, const GUID*);
+} ddraw_driver;
+
+void DDRAW_register_driver(const ddraw_driver*);
+
+const ddraw_driver* DDRAW_FindDriver(const GUID* guid);
+
+/******************************************************************************
+ * Random utilities
  */
-struct IDirectDrawSurface3Impl
-{
-    /* IUnknown fields */
-    ICOM_VFIELD(IDirectDrawSurface3);
-    DWORD                             ref;
-    /* IDirectDrawSurface3 fields */
-    struct _common_directdrawsurface	s;
-    LPVOID private;
-};
-
-/*****************************************************************************
- * IDirectDrawSurface4 implementation structure
- */
-struct IDirectDrawSurface4Impl
-{
-    /* IUnknown fields */
-    ICOM_VFIELD(IDirectDrawSurface4);
-    DWORD                             ref;
-
-    /* IDirectDrawSurface4 fields */
-    struct _common_directdrawsurface	s;
-    LPVOID private;
-} ;
-
-struct _surface_chain {
-	IDirectDrawSurface4Impl	**surfaces;
-	int			nrofsurfaces;
-};
-extern HRESULT common_off_screen_CreateSurface(IDirectDraw2Impl* This,IDirectDrawSurfaceImpl* lpdsf);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_Lock(LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_Unlock( LPDIRECTDRAWSURFACE4 iface,LPVOID surface);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_Blt(LPDIRECTDRAWSURFACE4 iface,LPRECT rdst,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,DWORD dwFlags,LPDDBLTFX lpbltfx);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_BltFast(LPDIRECTDRAWSURFACE4 iface,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,DWORD trans);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_BltBatch(LPDIRECTDRAWSURFACE4 iface,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetCaps(LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS caps);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetSurfaceDesc(LPDIRECTDRAWSURFACE4 iface,LPDDSURFACEDESC ddsd);
-extern ULONG WINAPI IDirectDrawSurface4Impl_AddRef(LPDIRECTDRAWSURFACE4 iface);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetAttachedSurface(LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE4 *lpdsf);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_Initialize(LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetPixelFormat(LPDIRECTDRAWSURFACE4 iface,LPDDPIXELFORMAT pf);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetBltStatus(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetOverlayPosition(LPDIRECTDRAWSURFACE4 iface,LPLONG x1,LPLONG x2);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_SetClipper(LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWCLIPPER lpClipper);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_AddAttachedSurface(LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 surf);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_ReleaseDC(LPDIRECTDRAWSURFACE4 iface,HDC hdc);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_QueryInterface(LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_IsLost(LPDIRECTDRAWSURFACE4 iface);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE4 iface,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_Restore(LPDIRECTDRAWSURFACE4 iface);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_SetColorKey(LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY ckey);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE4 iface,LPRECT lpRect);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_DeleteAttachedSurface(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags,LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_EnumOverlayZOrders(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpfnCallback);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetClipper(LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWCLIPPER* lplpDDClipper);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetColorKey(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags,LPDDCOLORKEY lpDDColorKey);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetFlipStatus(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetPalette(LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE* lplpDDPalette);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_SetOverlayPosition(LPDIRECTDRAWSURFACE4 iface,LONG lX,LONG lY);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlay(LPDIRECTDRAWSURFACE4 iface,LPRECT lpSrcRect,LPDIRECTDRAWSURFACE4 lpDDDestSurface,LPRECT lpDestRect,DWORD dwFlags,LPDDOVERLAYFX lpDDOverlayFx);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags,LPDIRECTDRAWSURFACE4 lpDDSReference);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetDDInterface(LPDIRECTDRAWSURFACE4 iface,LPVOID* lplpDD);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_PageLock(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_PageUnlock(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_SetSurfaceDesc(LPDIRECTDRAWSURFACE4 iface,LPDDSURFACEDESC lpDDSD,DWORD dwFlags);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_SetPrivateData(LPDIRECTDRAWSURFACE4 iface,REFGUID guidTag,LPVOID lpData,DWORD cbSize,DWORD dwFlags);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetPrivateData(LPDIRECTDRAWSURFACE4 iface,REFGUID guidTag,LPVOID lpBuffer,LPDWORD lpcbBufferSize);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_FreePrivateData(LPDIRECTDRAWSURFACE4 iface,REFGUID guidTag);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_GetUniquenessValue(LPDIRECTDRAWSURFACE4 iface,LPDWORD lpValue);
-extern HRESULT WINAPI IDirectDrawSurface4Impl_ChangeUniquenessValue(LPDIRECTDRAWSURFACE4 iface);
-
-extern void _common_IDirectDrawImpl_SetDisplayMode(IDirectDrawImpl* This);
 
 /* Get DDSCAPS of surface (shortcutmacro) */
 #define SDDSCAPS(iface) ((iface)->s.surface_desc.ddsCaps.dwCaps)
 /* Get the number of bytes per pixel for a given surface */
-#define PFGET_BPP(pf) (pf.dwFlags&DDPF_PALETTEINDEXED8?1:((pf.u.dwRGBBitCount+7)/8))
-#define GET_BPP(desc) PFGET_BPP(desc.ddpfPixelFormat)
+#define PFGET_BPP(pf) (pf.dwFlags&DDPF_PALETTEINDEXED8?1:((pf.u1.dwRGBBitCount+7)/8))
+#define GET_BPP(desc) PFGET_BPP(desc.u4.ddpfPixelFormat)
+
+LONG DDRAW_width_bpp_to_pitch(DWORD width, DWORD bpp);
 
 typedef struct {
     unsigned short	bpp,depth;
@@ -387,27 +281,33 @@
     ConvertFuncs funcs;
 } Convert;
 
-extern Convert ModeEmulations[7];
+extern Convert ModeEmulations[8];
 extern int _common_depth_to_pixelformat(DWORD depth,LPDIRECTDRAW ddraw);
 
-extern HRESULT create_direct3d(LPVOID *obj,IDirectDraw2Impl*);
-extern HRESULT create_direct3d2(LPVOID *obj,IDirectDraw2Impl*);
-extern HRESULT create_direct3d3(LPVOID *obj,IDirectDraw2Impl*);
+extern HRESULT create_direct3d(LPVOID *obj,IDirectDrawImpl*);
+extern HRESULT create_direct3d2(LPVOID *obj,IDirectDrawImpl*);
+extern HRESULT create_direct3d3(LPVOID *obj,IDirectDrawImpl*);
+extern HRESULT create_direct3d7(LPVOID *obj,IDirectDrawImpl*);
+
+/******************************************************************************
+ * Structure conversion (for thunks)
+ */
+void DDRAW_Convert_DDSCAPS_1_To_2(const DDSCAPS* pIn, DDSCAPS2* pOut);
+void DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(const DDDEVICEIDENTIFIER* pIn,
+					     DDDEVICEIDENTIFIER2* pOut);
 
 /******************************************************************************
  * Debugging / Flags output functions
  */
-extern void _dump_DDBLTFX(DWORD flagmask);
-extern void _dump_DDBLTFAST(DWORD flagmask);
-extern void _dump_DDBLT(DWORD flagmask);
-extern void _dump_DDSCAPS(void *in);
-extern void _dump_pixelformat_flag(DWORD flagmask);
-extern void _dump_paletteformat(DWORD dwFlags);
-extern void _dump_pixelformat(void *in);
-extern void _dump_colorkeyflag(DWORD ck);
-extern void _dump_surface_desc(DDSURFACEDESC *lpddsd);
-extern void _dump_cooperativelevel(DWORD cooplevel);
-extern void _dump_surface_desc(DDSURFACEDESC *lpddsd);
-extern void _dump_DDCOLORKEY(void *in);
-extern void _dump_DDOVERLAY(DWORD flagmask) ;
+extern void DDRAW_dump_DDBLTFX(DWORD flagmask);
+extern void DDRAW_dump_DDBLTFAST(DWORD flagmask);
+extern void DDRAW_dump_DDBLT(DWORD flagmask);
+extern void DDRAW_dump_DDSCAPS(const DDSCAPS2 *in);
+extern void DDRAW_dump_pixelformat_flag(DWORD flagmask);
+extern void DDRAW_dump_paletteformat(DWORD dwFlags);
+extern void DDRAW_dump_pixelformat(const DDPIXELFORMAT *in);
+extern void DDRAW_dump_colorkeyflag(DWORD ck);
+extern void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd);
+extern void DDRAW_dump_cooperativelevel(DWORD cooplevel);
+extern void DDRAW_dump_DDCOLORKEY(const DDCOLORKEY *in);
 #endif /* __WINE_DLLS_DDRAW_DDRAW_PRIVATE_H */
diff --git a/dlls/ddraw/direct3d/mesa.c b/dlls/ddraw/direct3d/mesa.c
index 709fdef..d7fa735 100644
--- a/dlls/ddraw/direct3d/mesa.c
+++ b/dlls/ddraw/direct3d/mesa.c
@@ -342,7 +342,7 @@
 #undef XCAST
 #endif
 
-HRESULT create_direct3d(LPVOID *obj,IDirectDraw2Impl* ddraw) {
+HRESULT create_direct3d(LPVOID *obj,IDirectDrawImpl* ddraw) {
     IDirect3DImpl* d3d;
 
     d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
@@ -357,7 +357,7 @@
     return S_OK;
 }
 
-HRESULT create_direct3d2(LPVOID *obj,IDirectDraw2Impl* ddraw) {
+HRESULT create_direct3d2(LPVOID *obj,IDirectDrawImpl* ddraw) {
     IDirect3D2Impl* d3d;
 
     d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
@@ -372,7 +372,7 @@
     return S_OK;
 }
 
-HRESULT create_direct3d3(LPVOID *obj,IDirectDraw2Impl* ddraw) {
+HRESULT create_direct3d3(LPVOID *obj,IDirectDrawImpl* ddraw) {
     IDirect3D3Impl* d3d;
 
     d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
diff --git a/dlls/ddraw/dpalette/dga.c b/dlls/ddraw/dpalette/dga.c
deleted file mode 100644
index 02747c8..0000000
--- a/dlls/ddraw/dpalette/dga.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*		DirectDrawPalette XF86DGA implementation
- *
- * Copyright 1997-2000 Marcus Meissner
- * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
- */
-
-#include "config.h"
-#include "winerror.h"
-
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "debugtools.h"
-
-#include "dga_private.h"
-
-DEFAULT_DEBUG_CHANNEL(ddraw);
-
-#define DPPRIVATE(x) dga_dp_private *dppriv = ((dga_dp_private*)(x)->private)
-#define DDPRIVATE(x) dga_dd_private *ddpriv = ((dga_dd_private*)(x)->d->private)
-
-HRESULT WINAPI DGA_IDirectDrawPaletteImpl_SetEntries(
-    LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
-) {
-    ICOM_THIS(IDirectDrawPaletteImpl,iface);
-    DPPRIVATE(This);
-    XColor	xc;
-    int		i;
-
-    TRACE("(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",This,x,start,count,palent);
-    if (!dppriv->cm) /* should not happen */ {
-	TRACE("app tried to set colormap in non-palettized mode\n");
-    }
-    for (i=0;i<count;i++) {
-	xc.red = palent[i].peRed<<8;
-	xc.blue = palent[i].peBlue<<8;
-	xc.green = palent[i].peGreen<<8;
-	xc.flags = DoRed|DoBlue|DoGreen;
-	xc.pixel = i+start;
-	
-	if (dppriv->cm)
-	  TSXStoreColor(display,dppriv->cm,&xc);
-
-	This->palents[start+i].peRed = palent[i].peRed;
-	This->palents[start+i].peBlue = palent[i].peBlue;
-	This->palents[start+i].peGreen = palent[i].peGreen;
-	This->palents[start+i].peFlags = palent[i].peFlags;
-    }
-    /* Flush the display queue so that palette updates are visible directly */
-    TSXFlush(display);
-    return DD_OK;
-}
-ICOM_VTABLE(IDirectDrawPalette) dga_ddpalvt = 
-{
-	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-	IDirectDrawPaletteImpl_QueryInterface,
-	IDirectDrawPaletteImpl_AddRef,
-	Xlib_IDirectDrawPaletteImpl_Release,
-	IDirectDrawPaletteImpl_GetCaps,
-	IDirectDrawPaletteImpl_GetEntries,
-	IDirectDrawPaletteImpl_Initialize,
-	DGA_IDirectDrawPaletteImpl_SetEntries
-};
diff --git a/dlls/ddraw/dpalette/main.c b/dlls/ddraw/dpalette/main.c
index 12b2dba..95bfca4 100644
--- a/dlls/ddraw/dpalette/main.c
+++ b/dlls/ddraw/dpalette/main.c
@@ -1,110 +1,259 @@
 /*		DirectDraw - IDirectPalette base interface
  *
  * Copyright 1997-2000 Marcus Meissner
+ * Copyright 2000 TransGaming Technologies Inc.
  */
 
 #include "config.h"
 #include "winerror.h"
-
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "ddraw_private.h"
 #include "debugtools.h"
 
+#include <assert.h>
+#include <string.h>
+
+#include "ddraw_private.h"
+#include "dpalette/main.h"
+#include "ddraw/main.h"
+
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
+#define SIZE_BITS (DDPCAPS_1BIT | DDPCAPS_2BIT | DDPCAPS_4BIT | DDPCAPS_8BIT)
+
+/* For unsigned x. 0 is not a power of 2. */
+#define IS_POW_2(x) (((x) & ((x) - 1)) == 0)
+
+static ICOM_VTABLE(IDirectDrawPalette) DDRAW_Main_Palette_VTable;
+
 /******************************************************************************
  *			IDirectDrawPalette
  */
-HRESULT WINAPI IDirectDrawPaletteImpl_GetEntries(
-    LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
-) {
-    ICOM_THIS(IDirectDrawPaletteImpl,iface);
-    int	i;
+HRESULT Main_DirectDrawPalette_Construct(IDirectDrawPaletteImpl* This,
+					 IDirectDrawImpl* pDD, DWORD dwFlags)
+{
+    if (!IS_POW_2(dwFlags & SIZE_BITS)) return DDERR_INVALIDPARAMS;
 
-    TRACE("(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",This,x,start,count,palent);
+    if (dwFlags & DDPCAPS_8BITENTRIES)
+	WARN("creating palette with 8 bit entries\n");
 
-    for (i=0;i<count;i++) {
-	palent[i].peRed   = This->palents[start+i].peRed;
-	palent[i].peBlue  = This->palents[start+i].peBlue;
-	palent[i].peGreen = This->palents[start+i].peGreen;
-	palent[i].peFlags = This->palents[start+i].peFlags;
-    }
+    This->flags = dwFlags;
+    This->palNumEntries = Main_DirectDrawPalette_Size(dwFlags);
+    This->ref = 1;
+    This->final_release = Main_DirectDrawPalette_final_release;
+    ICOM_INIT_INTERFACE(This, IDirectDrawPalette, DDRAW_Main_Palette_VTable);
+
+    /* we could defer hpal creation until we need it,
+     * but does anyone have a case where it would be useful? */
+    This->hpal = CreatePalette((const LOGPALETTE*)&(This->palVersion));
+
+    Main_DirectDraw_AddPalette(pDD, This);
+
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDrawPaletteImpl_SetEntries(
-    LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
-) {
-    ICOM_THIS(IDirectDrawPaletteImpl,iface);
-    int		i;
+HRESULT
+Main_DirectDrawPalette_Create(IDirectDrawImpl* pDD, DWORD dwFlags,
+			      LPDIRECTDRAWPALETTE* ppPalette,
+			      LPUNKNOWN pUnkOuter)
+{
+    IDirectDrawPaletteImpl* This;
+    HRESULT hr;
 
-    TRACE("(%p)->SetEntries(%08lx,%ld,%ld,%p)\n", This,x,start,count,palent);
-    for (i=0;i<count;i++) {
-	This->palents[start+i].peRed = palent[i].peRed;
-	This->palents[start+i].peBlue = palent[i].peBlue;
-	This->palents[start+i].peGreen = palent[i].peGreen;
-	This->palents[start+i].peFlags = palent[i].peFlags;
+    if (pUnkOuter != NULL)
+	return CLASS_E_NOAGGREGATION; /* unchecked */
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    hr = Main_DirectDrawPalette_Construct(This, pDD, dwFlags);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*ppPalette = ICOM_INTERFACE(This, IDirectDrawPalette);
+
+    return hr;
+}
+
+DWORD Main_DirectDrawPalette_Size(DWORD dwFlags)
+{
+    switch (dwFlags & SIZE_BITS)
+    {
+    case DDPCAPS_1BIT: return 2;
+    case DDPCAPS_2BIT: return 4;
+    case DDPCAPS_4BIT: return 16;
+    case DDPCAPS_8BIT: return 256;
+    default: assert(0); return 256;
+    }
+}
+
+HRESULT WINAPI
+Main_DirectDrawPalette_GetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
+				  DWORD dwStart, DWORD dwCount,
+				  LPPALETTEENTRY palent)
+{
+    ICOM_THIS(IDirectDrawPaletteImpl,iface);
+
+    TRACE("(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",This,dwFlags,dwStart,dwCount,
+	  palent);
+
+    if (dwFlags != 0) return DDERR_INVALIDPARAMS; /* unchecked */
+    if (dwStart + dwCount > Main_DirectDrawPalette_Size(This->flags))
+	return DDERR_INVALIDPARAMS;
+
+    if (This->flags & DDPCAPS_8BITENTRIES)
+    {
+	int i;
+	LPBYTE entry = (LPBYTE)palent;
+
+	for (i=dwStart; i < dwCount+dwStart; i++)
+	    *entry++ = This->palents[i].peRed;
+    }
+    else
+	memcpy(palent, This->palents+dwStart, dwCount * sizeof(PALETTEENTRY));
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawPalette_SetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
+				  DWORD dwStart, DWORD dwCount,
+				  LPPALETTEENTRY palent)
+{
+    ICOM_THIS(IDirectDrawPaletteImpl,iface);
+
+    TRACE("(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",This,dwFlags,dwStart,dwCount,
+	  palent);
+
+    if (This->flags & DDPCAPS_8BITENTRIES)
+    {
+	int i;
+	const BYTE* entry = (const BYTE*)palent;
+
+	for (i=dwStart; i < dwCount+dwStart; i++)
+	    This->palents[i].peRed = *entry++;
+    }
+    else {
+	memcpy(This->palents+dwStart, palent, dwCount * sizeof(PALETTEENTRY));
+
+	if (This->hpal)
+	    SetPaletteEntries(This->hpal, dwStart, dwCount, This->palents+dwStart);
+
+	if (This->flags & DDPCAPS_PRIMARYSURFACE) {
+	    /* update physical palette */
+	    LPDIRECTDRAWSURFACE7 psurf = NULL;
+	    IDirectDraw7_GetGDISurface(ICOM_INTERFACE(This->ddraw_owner,IDirectDraw7), &psurf);
+	    if (psurf) {
+		IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
+							   IDirectDrawSurface7, psurf);
+		surf->update_palette(surf, This, dwStart, dwCount, palent);
+		IDirectDrawSurface7_Release(psurf);
+	    }
+	    else ERR("can't find GDI surface!!\n");
+	}
     }
 
+#if 0
     /* Now, if we are in 'depth conversion mode', update the screen palette */
     /* FIXME: we need to update the image or we won't get palette fading. */
     if (This->ddraw->d->palette_convert != NULL)
 	This->ddraw->d->palette_convert(palent,This->screen_palents,start,count);
+#endif
+
     return DD_OK;
 }
 
-ULONG WINAPI IDirectDrawPaletteImpl_Release(LPDIRECTDRAWPALETTE iface) {
+void Main_DirectDrawPalette_final_release(IDirectDrawPaletteImpl* This)
+{
+    Main_DirectDraw_RemovePalette(This->ddraw_owner, This);
+
+    if (This->hpal) DeleteObject(This->hpal);
+}
+
+static void Main_DirectDrawPalette_Destroy(IDirectDrawPaletteImpl* This)
+{
+    This->final_release(This);
+
+    if (This->private != This+1)
+	HeapFree(GetProcessHeap(), 0, This->private);
+		     
+    HeapFree(GetProcessHeap(),0,This);
+}
+
+void Main_DirectDrawPalette_ForceDestroy(IDirectDrawPaletteImpl* This)
+{
+    WARN("deleting palette %p with refcnt %lu\n", This, This->ref);
+    Main_DirectDrawPalette_Destroy(This);
+}
+
+ULONG WINAPI
+Main_DirectDrawPalette_Release(LPDIRECTDRAWPALETTE iface)
+{
     ICOM_THIS(IDirectDrawPaletteImpl,iface);
     TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
-    if (!--(This->ref)) {
-	    HeapFree(GetProcessHeap(),0,This);
-	    return S_OK;
+
+    if (!--This->ref)
+    {
+	Main_DirectDrawPalette_Destroy(This);
+	return 0;
     }
+
     return This->ref;
 }
 
-ULONG WINAPI IDirectDrawPaletteImpl_AddRef(LPDIRECTDRAWPALETTE iface) {
+ULONG WINAPI Main_DirectDrawPalette_AddRef(LPDIRECTDRAWPALETTE iface) {
     ICOM_THIS(IDirectDrawPaletteImpl,iface);
     TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
-    return ++(This->ref);
+    return ++This->ref;
 }
 
-HRESULT WINAPI IDirectDrawPaletteImpl_Initialize(
-    LPDIRECTDRAWPALETTE iface,LPDIRECTDRAW ddraw,DWORD x,LPPALETTEENTRY palent
-) {
+HRESULT WINAPI
+Main_DirectDrawPalette_Initialize(LPDIRECTDRAWPALETTE iface,
+				  LPDIRECTDRAW ddraw, DWORD dwFlags,
+				  LPPALETTEENTRY palent)
+{
     ICOM_THIS(IDirectDrawPaletteImpl,iface);
-    TRACE("(%p)->(%p,%ld,%p)\n", This, ddraw, x, palent);
+    TRACE("(%p)->(%p,%ld,%p)\n", This, ddraw, dwFlags, palent);
     return DDERR_ALREADYINITIALIZED;
 }
 
-HRESULT WINAPI IDirectDrawPaletteImpl_GetCaps(
-     LPDIRECTDRAWPALETTE iface, LPDWORD lpdwCaps )
+HRESULT WINAPI
+Main_DirectDrawPalette_GetCaps(LPDIRECTDRAWPALETTE iface, LPDWORD lpdwCaps)
 {
    ICOM_THIS(IDirectDrawPaletteImpl,iface);
-   FIXME("(%p)->(%p) stub.\n", This, lpdwCaps );
+   TRACE("(%p)->(%p)\n",This,lpdwCaps);
+
+   *lpdwCaps = This->flags;
+
    return DD_OK;
 } 
 
-HRESULT WINAPI IDirectDrawPaletteImpl_QueryInterface(
-    LPDIRECTDRAWPALETTE iface,REFIID refiid,LPVOID *obj ) 
+HRESULT WINAPI
+Main_DirectDrawPalette_QueryInterface(LPDIRECTDRAWPALETTE iface,
+				      REFIID refiid, LPVOID *obj)
 {
     ICOM_THIS(IDirectDrawPaletteImpl,iface);
-    FIXME("(%p)->(%s,%p) stub.\n",This,debugstr_guid(refiid),obj);
-    return S_OK;
+    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
+
+    if (IsEqualGUID(refiid, &IID_IUnknown)
+	|| IsEqualGUID(refiid, &IID_IDirectDrawPalette))
+    {
+	*obj = iface;
+	IDirectDrawPalette_AddRef(iface);
+	return S_OK;
+    }
+    else
+    {
+	return E_NOINTERFACE;
+    }
 }
 
-ICOM_VTABLE(IDirectDrawPalette) ddraw_ddpalvt = 
+static ICOM_VTABLE(IDirectDrawPalette) DDRAW_Main_Palette_VTable =
 {
     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    IDirectDrawPaletteImpl_QueryInterface,
-    IDirectDrawPaletteImpl_AddRef,
-    IDirectDrawPaletteImpl_Release,
-    IDirectDrawPaletteImpl_GetCaps,
-    IDirectDrawPaletteImpl_GetEntries,
-    IDirectDrawPaletteImpl_Initialize,
-    IDirectDrawPaletteImpl_SetEntries
+    Main_DirectDrawPalette_QueryInterface,
+    Main_DirectDrawPalette_AddRef,
+    Main_DirectDrawPalette_Release,
+    Main_DirectDrawPalette_GetCaps,
+    Main_DirectDrawPalette_GetEntries,
+    Main_DirectDrawPalette_Initialize,
+    Main_DirectDrawPalette_SetEntries
 };
diff --git a/dlls/ddraw/dpalette/main.h b/dlls/ddraw/dpalette/main.h
new file mode 100644
index 0000000..7edefea
--- /dev/null
+++ b/dlls/ddraw/dpalette/main.h
@@ -0,0 +1,44 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef WINE_DDRAW_DPALETTE_MAIN_H_INCLUDED
+#define WINE_DDRAW_DPALETTE_MAIN_H_INCLUDED
+
+HRESULT Main_DirectDrawPalette_Construct(IDirectDrawPaletteImpl* This,
+					 IDirectDrawImpl* pDD, DWORD dwFlags);
+void Main_DirectDrawPalette_final_release(IDirectDrawPaletteImpl* This);
+
+
+HRESULT
+Main_DirectDrawPalette_Create(IDirectDrawImpl* pDD, DWORD dwFlags,
+			      LPDIRECTDRAWPALETTE* ppPalette,
+			      LPUNKNOWN pUnkOuter);
+void Main_DirectDrawPalette_ForceDestroy(IDirectDrawPaletteImpl* This);
+
+
+DWORD Main_DirectDrawPalette_Size(DWORD dwFlags);
+
+
+
+HRESULT WINAPI
+Main_DirectDrawPalette_GetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
+				  DWORD dwStart, DWORD dwCount,
+				  LPPALETTEENTRY palent);
+HRESULT WINAPI
+Main_DirectDrawPalette_SetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
+				  DWORD dwStart, DWORD dwCount,
+				  LPPALETTEENTRY palent);
+ULONG WINAPI
+Main_DirectDrawPalette_Release(LPDIRECTDRAWPALETTE iface);
+ULONG WINAPI Main_DirectDrawPalette_AddRef(LPDIRECTDRAWPALETTE iface);
+HRESULT WINAPI
+Main_DirectDrawPalette_Initialize(LPDIRECTDRAWPALETTE iface,
+				  LPDIRECTDRAW ddraw, DWORD dwFlags,
+				  LPPALETTEENTRY palent);
+HRESULT WINAPI
+Main_DirectDrawPalette_GetCaps(LPDIRECTDRAWPALETTE iface, LPDWORD lpdwCaps);
+HRESULT WINAPI
+Main_DirectDrawPalette_QueryInterface(LPDIRECTDRAWPALETTE iface,
+				      REFIID refiid, LPVOID *obj);
+
+
+#endif
diff --git a/dlls/ddraw/dpalette/x11.c b/dlls/ddraw/dpalette/x11.c
deleted file mode 100644
index bebe698..0000000
--- a/dlls/ddraw/dpalette/x11.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*		DirectDraw IDirectDrawPalette X11 implementation
- *
- * Copyright 1997-2000 Marcus Meissner
- */
-
-#include "config.h"
-#include "winerror.h"
-
-
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "debugtools.h"
-
-#include "x11_private.h"
-
-DEFAULT_DEBUG_CHANNEL(ddraw);
-
-#define DPPRIVATE(x) x11_dp_private *dppriv = ((x11_dp_private*)x->private)
-
-/******************************************************************************
- *			IDirectDrawPalette
- */
-
-HRESULT WINAPI Xlib_IDirectDrawPaletteImpl_SetEntries(
-    LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
-) {
-    ICOM_THIS(IDirectDrawPaletteImpl,iface);
-    XColor	xc;
-    int		i;
-    DPPRIVATE(This);
-
-    TRACE("(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",This,x,start,count,palent);
-    for (i=0;i<count;i++) {
-	xc.red = palent[i].peRed<<8;
-	xc.blue = palent[i].peBlue<<8;
-	xc.green = palent[i].peGreen<<8;
-	xc.flags = DoRed|DoBlue|DoGreen;
-	xc.pixel = start+i;
-
-	if (dppriv->cm)
-	    TSXStoreColor(display,dppriv->cm,&xc);
-
-	This->palents[start+i].peRed = palent[i].peRed;
-	This->palents[start+i].peBlue = palent[i].peBlue;
-	This->palents[start+i].peGreen = palent[i].peGreen;
-	This->palents[start+i].peFlags = palent[i].peFlags;
-    }
-
-    /* Now, if we are in 'depth conversion mode', update the screen palette */
-    /* FIXME: we need to update the image or we won't get palette fading. */
-    if (This->ddraw->d->palette_convert != NULL) {
-	This->ddraw->d->palette_convert(palent,This->screen_palents,start,count);
-    }
-    return DD_OK;
-}
-
-ULONG WINAPI Xlib_IDirectDrawPaletteImpl_Release(LPDIRECTDRAWPALETTE iface) {
-    ICOM_THIS(IDirectDrawPaletteImpl,iface);
-    DPPRIVATE(This);
-    TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
-    if (!--(This->ref)) {
-	if (dppriv->cm) {
-	    TSXFreeColormap(display,dppriv->cm);
-	    dppriv->cm = 0;
-	}
-	HeapFree(GetProcessHeap(),0,This);
-	return S_OK;
-    }
-    return This->ref;
-}
-
-ICOM_VTABLE(IDirectDrawPalette) xlib_ddpalvt = 
-{
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    IDirectDrawPaletteImpl_QueryInterface,
-    IDirectDrawPaletteImpl_AddRef,
-    Xlib_IDirectDrawPaletteImpl_Release,
-    IDirectDrawPaletteImpl_GetCaps,
-    IDirectDrawPaletteImpl_GetEntries,
-    IDirectDrawPaletteImpl_Initialize,
-    Xlib_IDirectDrawPaletteImpl_SetEntries
-};
diff --git a/dlls/ddraw/dsurface/dga.c b/dlls/ddraw/dsurface/dga.c
deleted file mode 100644
index 6a19205..0000000
--- a/dlls/ddraw/dsurface/dga.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*		DirectDrawSurface XF86DGA implementation
- *
- * Copyright 1997-2000 Marcus Meissner
- * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
- */
-#include "config.h"
-#include "winerror.h"
-
-#include <unistd.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "debugtools.h"
-#include "dga_private.h"
-#include "bitmap.h"
-
-DEFAULT_DEBUG_CHANNEL(ddraw);
-
-#define DDPRIVATE(x) dga_dd_private *ddpriv = ((dga_dd_private*)(x)->d->private)
-#define DPPRIVATE(x) dga_dp_private *dppriv = ((dga_dp_private*)(x)->private)
-#define DSPRIVATE(x) dga_ds_private *dspriv = ((dga_ds_private*)(x)->private)
-
-static BYTE DGA_TouchSurface(LPDIRECTDRAWSURFACE4 iface)
-{
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    /* if the DIB section is in GdiMod state, we must
-     * touch the surface to get any updates from the DIB */
-    return *(BYTE*)(This->s.surface_desc.u1.lpSurface);
-}
-
-/******************************************************************************
- *		IDirectDrawSurface methods
- *
- * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
- * DDS and DDS2 use those functions. (Function calls did not change (except
- * using different DirectDrawSurfaceX version), just added flags and functions)
- */
-
-HRESULT WINAPI DGA_IDirectDrawSurface4Impl_Flip(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DSPRIVATE(This);
-    dga_ds_private	*fspriv;
-    IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
-    DWORD		xheight;
-    LPBYTE		surf;
-
-    TRACE("(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
-
-    DGA_TouchSurface(iface);
-    iflipto = _common_find_flipto(This,iflipto);
-
-    /* and flip! */
-    fspriv = (dga_ds_private*)iflipto->private;
-    TSXF86DGASetViewPort(display,DefaultScreen(display),0,fspriv->fb_height);
-    if (iflipto->s.palette) {
-	DPPRIVATE(iflipto);
-	
-	if (dppriv->cm)
-	    TSXF86DGAInstallColormap(display,DefaultScreen(display),dppriv->cm);
-    }
-    while (!TSXF86DGAViewPortChanged(display,DefaultScreen(display),2)) {
-	/* EMPTY */
-    }
-    /* We need to switch the lowlevel surfaces, for DGA this is: */
-
-    /* The height within the framebuffer */
-    xheight		= dspriv->fb_height;
-    dspriv->fb_height	= fspriv->fb_height;
-    fspriv->fb_height	= xheight;
-
-    /* And the assciated surface pointer */
-    surf				= This->s.surface_desc.u1.lpSurface;
-    This->s.surface_desc.u1.lpSurface	= iflipto->s.surface_desc.u1.lpSurface;
-    iflipto->s.surface_desc.u1.lpSurface= surf;
-    return DD_OK;
-}
-
-HRESULT WINAPI DGA_IDirectDrawSurface4Impl_SetPalette(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
-
-    TRACE("(%p)->(%p)\n",This,ipal);
-
-    /* According to spec, we are only supposed to 
-     * AddRef if this is not the same palette.
-     */
-    if( This->s.palette != ipal ) {
-	dga_dp_private	*fppriv;
-	if( ipal != NULL )
-	    IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
-	if( This->s.palette != NULL )
-	    IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
-	This->s.palette = ipal;
-	fppriv = (dga_dp_private*)This->s.palette->private;
-
-	if (!fppriv->cm &&
-	    (This->s.ddraw->d->screen_pixelformat.u.dwRGBBitCount<=8) ) {
-	  int i;
-	  
-	  /* Delayed palette creation */
-	  fppriv->cm = TSXCreateColormap(display,DefaultRootWindow(display),
-					 DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
-	    
-	  for (i=0;i<256;i++) {
-	    XColor xc;
-	    
-	    xc.red		= ipal->palents[i].peRed<<8;
-	    xc.blue		= ipal->palents[i].peBlue<<8;
-	    xc.green	= ipal->palents[i].peGreen<<8;
-	    xc.flags	= DoRed|DoBlue|DoGreen;
-	    xc.pixel	= i;
-	    TSXStoreColor(display,fppriv->cm,&xc);
-	  }
-	}
-
-	TSXF86DGAInstallColormap(display,DefaultScreen(display),fppriv->cm);
-
-        if (This->s.hdc != 0) {
-	    /* hack: set the DIBsection color map */
-	    BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
-	    X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
-	    dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	    GDI_ReleaseObj(This->s.DIBsection);
-	}
-	TSXFlush(display);
-    }
-    return DD_OK;
-}
-
-ULONG WINAPI DGA_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DDPRIVATE(This->s.ddraw);
-    DSPRIVATE(This);
-
-    TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
-
-    if (--(This->ref))
-    	return This->ref;
-
-    IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
-    /* clear out of surface list */
-    if (ddpriv->fb_height == -1)
-	VirtualFree(This->s.surface_desc.u1.lpSurface, 0, MEM_RELEASE);
-    else
-	ddpriv->vpmask &= ~(1<<(dspriv->fb_height/ddpriv->fb_height));
-
-    /* Free the DIBSection (if any) */
-    if (This->s.hdc != 0) {
-	/* hack: restore the original DIBsection color map */    
-	BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
-	X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
-	dib->colorMap = dspriv->oldDIBmap;
-	GDI_ReleaseObj(This->s.DIBsection);
-
-	SelectObject(This->s.hdc, This->s.holdbitmap);
-	DeleteDC(This->s.hdc);
-	DeleteObject(This->s.DIBsection);
-    }
-    /* Free the clipper if attached to this surface */
-    if( This->s.lpClipper )
-	IDirectDrawClipper_Release(This->s.lpClipper);
-    HeapFree(GetProcessHeap(),0,This);
-    return S_OK;
-}
-
-HRESULT WINAPI DGA_IDirectDrawSurface4Impl_Unlock(
-    LPDIRECTDRAWSURFACE4 iface,LPVOID surface
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->Unlock(%p)\n",This,surface);
-
-    /* in case this was called from ReleaseDC */
-    DGA_TouchSurface(iface);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI DGA_IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);                                             
-    DSPRIVATE(This);
-    int was_ok = This->s.hdc != 0;
-    HRESULT result = IDirectDrawSurface4Impl_GetDC(iface,lphdc);
-    if (This->s.hdc && !was_ok) {                               
-	/* hack: take over the DIBsection color map */
-	BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
-	X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
-	dspriv->oldDIBmap = dib->colorMap;
-	dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	GDI_ReleaseObj(This->s.DIBsection);
-    }
-    return result;
-}
-
-ICOM_VTABLE(IDirectDrawSurface4) dga_dds4vt = 
-{
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    IDirectDrawSurface4Impl_QueryInterface,
-    IDirectDrawSurface4Impl_AddRef,
-    DGA_IDirectDrawSurface4Impl_Release,
-    IDirectDrawSurface4Impl_AddAttachedSurface,
-    IDirectDrawSurface4Impl_AddOverlayDirtyRect,
-    IDirectDrawSurface4Impl_Blt,
-    IDirectDrawSurface4Impl_BltBatch,
-    IDirectDrawSurface4Impl_BltFast,
-    IDirectDrawSurface4Impl_DeleteAttachedSurface,
-    IDirectDrawSurface4Impl_EnumAttachedSurfaces,
-    IDirectDrawSurface4Impl_EnumOverlayZOrders,
-    DGA_IDirectDrawSurface4Impl_Flip,
-    IDirectDrawSurface4Impl_GetAttachedSurface,
-    IDirectDrawSurface4Impl_GetBltStatus,
-    IDirectDrawSurface4Impl_GetCaps,
-    IDirectDrawSurface4Impl_GetClipper,
-    IDirectDrawSurface4Impl_GetColorKey,
-    DGA_IDirectDrawSurface4Impl_GetDC,
-    IDirectDrawSurface4Impl_GetFlipStatus,
-    IDirectDrawSurface4Impl_GetOverlayPosition,
-    IDirectDrawSurface4Impl_GetPalette,
-    IDirectDrawSurface4Impl_GetPixelFormat,
-    IDirectDrawSurface4Impl_GetSurfaceDesc,
-    IDirectDrawSurface4Impl_Initialize,
-    IDirectDrawSurface4Impl_IsLost,
-    IDirectDrawSurface4Impl_Lock,
-    IDirectDrawSurface4Impl_ReleaseDC,
-    IDirectDrawSurface4Impl_Restore,
-    IDirectDrawSurface4Impl_SetClipper,
-    IDirectDrawSurface4Impl_SetColorKey,
-    IDirectDrawSurface4Impl_SetOverlayPosition,
-    DGA_IDirectDrawSurface4Impl_SetPalette,
-    DGA_IDirectDrawSurface4Impl_Unlock,
-    IDirectDrawSurface4Impl_UpdateOverlay,
-    IDirectDrawSurface4Impl_UpdateOverlayDisplay,
-    IDirectDrawSurface4Impl_UpdateOverlayZOrder,
-    IDirectDrawSurface4Impl_GetDDInterface,
-    IDirectDrawSurface4Impl_PageLock,
-    IDirectDrawSurface4Impl_PageUnlock,
-    IDirectDrawSurface4Impl_SetSurfaceDesc,
-    IDirectDrawSurface4Impl_SetPrivateData,
-    IDirectDrawSurface4Impl_GetPrivateData,
-    IDirectDrawSurface4Impl_FreePrivateData,
-    IDirectDrawSurface4Impl_GetUniquenessValue,
-    IDirectDrawSurface4Impl_ChangeUniquenessValue
-};
diff --git a/dlls/ddraw/dsurface/dga2.c b/dlls/ddraw/dsurface/dga2.c
index b253fa0..53bcc2d 100644
--- a/dlls/ddraw/dsurface/dga2.c
+++ b/dlls/ddraw/dsurface/dga2.c
@@ -1,176 +1,253 @@
-/*		DirectDrawSurface XF86DGA implementation
+/*	XF86DGA2 primary surface driver
  *
- * DGA2's specific DirectDrawSurface routines
+ * Copyright 2000 TransGaming Technologies Inc.
  */
+
 #include "config.h"
+
+#ifdef HAVE_LIBXXF86DGA2
+
+#include "ts_xlib.h"
+#include "ts_xf86dga2.h"
+#include "x11drv.h"
 #include "winerror.h"
 
-#include <unistd.h>
 #include <assert.h>
-#include <fcntl.h>
-#include <string.h>
 #include <stdlib.h>
-#include <stdio.h>
 
 #include "debugtools.h"
-#include "dga2_private.h"
-#include "bitmap.h"
+#include "ddraw_private.h"
+#include "ddraw/user.h"
+#include "ddraw/dga2.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/dga2.h"
 
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
-#define DDPRIVATE(x) dga2_dd_private *ddpriv = ((dga2_dd_private*)(x)->d->private)
-#define DPPRIVATE(x) dga2_dp_private *dppriv = ((dga2_dp_private*)(x)->private)
-#define DSPRIVATE(x) dga2_ds_private *dspriv = ((dga2_ds_private*)(x)->private)
+static ICOM_VTABLE(IDirectDrawSurface7) XF86DGA2_IDirectDrawSurface7_VTable;
 
-static BYTE DGA2_TouchSurface(LPDIRECTDRAWSURFACE4 iface)
-{   
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    /* if the DIB section is in GdiMod state, we must
-     * touch the surface to get any updates from the DIB */
-    return *(BYTE*)(This->s.surface_desc.u1.lpSurface);
-}
+HRESULT
+XF86DGA2_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				     IDirectDrawImpl* pDD,
+				     const DDSURFACEDESC2* pDDSD)
+{
+    XF86DGA2_PRIV_VAR(priv, This);
+    XF86DGA2_DDRAW_PRIV_VAR(ddpriv, pDD);
+    HRESULT hr;
+    XDGADevice* mode;
 
-HRESULT WINAPI DGA2_IDirectDrawSurface4Impl_Flip(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
-    DWORD	xheight;
-    DSPRIVATE(This);
-    dga_ds_private	*fspriv;
-    LPBYTE	surf;
-
-    TRACE("(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
-
-    DGA2_TouchSurface(iface);
-    iflipto = _common_find_flipto(This,iflipto);
-
-    /* and flip! */
-    fspriv = (dga_ds_private*)iflipto->private;
-    TSXDGASetViewport(display,DefaultScreen(display),0,fspriv->fb_height, XDGAFlipRetrace);
-    TSXDGASync(display,DefaultScreen(display));
-    TSXFlush(display);
-    if (iflipto->s.palette) {
-	DPPRIVATE(iflipto->s.palette);
-	if (dppriv->cm)
-	    TSXDGAInstallColormap(display,DefaultScreen(display),dppriv->cm);
+    TRACE("(%p,%p,%p)\n",This,pDD,pDDSD);
+    if (!ddpriv->xf86dga2.current_mode) {
+	/* we need a mode! */
+	hr = XF86DGA2_DirectDraw_SetDisplayMode(ICOM_INTERFACE(pDD, IDirectDraw7),
+						pDD->width, pDD->height,
+						pDD->pixelformat.u1.dwRGBBitCount,
+						0, 0);
+	if (FAILED(hr)) return hr;
     }
 
-    /* We need to switch the lowlevel surfaces, for DGA this is: */
-    /* The height within the framebuffer */
-    xheight		= dspriv->fb_height;
-    dspriv->fb_height	= fspriv->fb_height;
-    fspriv->fb_height	= xheight;
+    /* grab framebuffer data from current_mode */
+    mode = ddpriv->xf86dga2.current_mode;
+    priv->xf86dga2.fb_pitch = mode->mode.bytesPerScanline;
+    priv->xf86dga2.fb_vofs  = ddpriv->xf86dga2.next_vofs;
+    priv->xf86dga2.fb_addr  = mode->data +
+			      priv->xf86dga2.fb_pitch * priv->xf86dga2.fb_vofs;
+    TRACE("vofs=%ld, addr=%p\n", priv->xf86dga2.fb_vofs, priv->xf86dga2.fb_addr);
 
-    /* And the assciated surface pointer */
-    surf	                         = This->s.surface_desc.u1.lpSurface;
-    This->s.surface_desc.u1.lpSurface    = iflipto->s.surface_desc.u1.lpSurface;
-    iflipto->s.surface_desc.u1.lpSurface = surf;
+    /* fill in surface_desc before we construct DIB from it */
+    This->surface_desc = *pDDSD;
+    This->surface_desc.lpSurface = priv->xf86dga2.fb_addr;
+    This->surface_desc.u1.lPitch = priv->xf86dga2.fb_pitch;
+    This->surface_desc.dwFlags |= DDSD_LPSURFACE | DDSD_PITCH;
+
+    hr = DIB_DirectDrawSurface_Construct(This, pDD, &This->surface_desc);
+    if (FAILED(hr)) return hr;
+
+    if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
+	priv->xf86dga2.pal = TSXDGACreateColormap(display, DefaultScreen(display), mode, AllocAll);
+	TSXDGAInstallColormap(display, DefaultScreen(display), priv->xf86dga2.pal);
+    }
+
+    ddpriv->xf86dga2.next_vofs += pDDSD->dwHeight;
+
+    ICOM_INIT_INTERFACE(This, IDirectDrawSurface7,
+			XF86DGA2_IDirectDrawSurface7_VTable);
+
+    This->final_release = XF86DGA2_DirectDrawSurface_final_release;
+    This->duplicate_surface = XF86DGA2_DirectDrawSurface_duplicate_surface;
+
+    This->flip_data   = XF86DGA2_DirectDrawSurface_flip_data;
+    This->flip_update = XF86DGA2_DirectDrawSurface_flip_update;
+
+    This->set_palette    = XF86DGA2_DirectDrawSurface_set_palette;
+    This->update_palette = XF86DGA2_DirectDrawSurface_update_palette;
+
+    This->get_display_window = XF86DGA2_DirectDrawSurface_get_display_window;
 
     return DD_OK;
 }
 
-HRESULT WINAPI DGA2_IDirectDrawSurface4Impl_SetPalette(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DDPRIVATE(This->s.ddraw);
-    IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
+HRESULT
+XF86DGA2_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+			      const DDSURFACEDESC2 *pDDSD,
+			      LPDIRECTDRAWSURFACE7 *ppSurf,
+			      IUnknown *pUnkOuter)
+{
+    IDirectDrawSurfaceImpl* This;
+    HRESULT hr;
+    assert(pUnkOuter == NULL);
 
-    TRACE("(%p)->(%p)\n",This,ipal);
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(*This) + sizeof(XF86DGA2_DirectDrawSurfaceImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
 
-    /* According to spec, we are only supposed to 
-     * AddRef if this is not the same palette.
-     */
-    if( This->s.palette != ipal ) {
-	dga_dp_private	*fppriv;
-	if( ipal != NULL )
-	    IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
-	if( This->s.palette != NULL )
-	    IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
-	This->s.palette = ipal;
-	fppriv = (dga_dp_private*)This->s.palette->private;
+    This->private = (XF86DGA2_DirectDrawSurfaceImpl*)(This+1);
 
-	if (!fppriv->cm &&
-	    (This->s.ddraw->d->screen_pixelformat.u.dwRGBBitCount<=8) ) {
-	  int i;
-	  
-	  /* Delayed palette creation */
-	  fppriv->cm = TSXDGACreateColormap(display,DefaultScreen(display), ddpriv->dev, AllocAll);
-	    
-	  for (i=0;i<256;i++) {
-	    XColor xc;
-	    
-	    xc.red		= ipal->palents[i].peRed<<8;
-	    xc.blue		= ipal->palents[i].peBlue<<8;
-	    xc.green	= ipal->palents[i].peGreen<<8;
-	    xc.flags	= DoRed|DoBlue|DoGreen;
-	    xc.pixel	= i;
-	    TSXStoreColor(display,fppriv->cm,&xc);
-	  }
-	}
+    hr = XF86DGA2_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7);
 
-	TSXDGAInstallColormap(display,DefaultScreen(display),fppriv->cm);
+    return hr;
+}
 
-        if (This->s.hdc != 0) {
-	    /* hack: set the DIBsection color map */
-	    BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
-	    X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
-	    dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	    GDI_ReleaseObj(This->s.DIBsection);
+void XF86DGA2_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
+{
+    XF86DGA2_PRIV_VAR(priv, This);
+
+    DIB_DirectDrawSurface_final_release(This);
+    if (priv->xf86dga2.pal)
+	TSXFreeColormap(display, priv->xf86dga2.pal);
+}
+
+void XF86DGA2_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+					IDirectDrawPaletteImpl* pal) 
+{
+    DIB_DirectDrawSurface_set_palette(This, pal);
+}
+
+void XF86DGA2_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+					   IDirectDrawPaletteImpl* pal,
+					   DWORD dwStart, DWORD dwCount,
+					   LPPALETTEENTRY palent)
+{
+    XF86DGA2_PRIV_VAR(priv, This);
+
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+	XColor c;
+	int n;
+
+	c.flags = DoRed|DoGreen|DoBlue;
+	c.pixel = dwStart;
+	for (n=0; n<dwCount; n++,c.pixel++) {
+	    c.red   = palent[n].peRed   << 8;
+	    c.green = palent[n].peGreen << 8;
+	    c.blue  = palent[n].peBlue  << 8;
+	    TSXStoreColor(display, priv->xf86dga2.pal, &c);
 	}
 	TSXFlush(display);
     }
-    return DD_OK;
 }
 
-
-ICOM_VTABLE(IDirectDrawSurface4) dga2_dds4vt = 
+HRESULT XF86DGA2_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						 LPDIRECTDRAWSURFACE7* ppDup)
 {
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    IDirectDrawSurface4Impl_QueryInterface,
-    IDirectDrawSurface4Impl_AddRef,
-    DGA_IDirectDrawSurface4Impl_Release,
-    IDirectDrawSurface4Impl_AddAttachedSurface,
-    IDirectDrawSurface4Impl_AddOverlayDirtyRect,
-    IDirectDrawSurface4Impl_Blt,
-    IDirectDrawSurface4Impl_BltBatch,
-    IDirectDrawSurface4Impl_BltFast,
-    IDirectDrawSurface4Impl_DeleteAttachedSurface,
-    IDirectDrawSurface4Impl_EnumAttachedSurfaces,
-    IDirectDrawSurface4Impl_EnumOverlayZOrders,
-    DGA2_IDirectDrawSurface4Impl_Flip,
-    IDirectDrawSurface4Impl_GetAttachedSurface,
-    IDirectDrawSurface4Impl_GetBltStatus,
-    IDirectDrawSurface4Impl_GetCaps,
-    IDirectDrawSurface4Impl_GetClipper,
-    IDirectDrawSurface4Impl_GetColorKey,
-    DGA_IDirectDrawSurface4Impl_GetDC,
-    IDirectDrawSurface4Impl_GetFlipStatus,
-    IDirectDrawSurface4Impl_GetOverlayPosition,
-    IDirectDrawSurface4Impl_GetPalette,
-    IDirectDrawSurface4Impl_GetPixelFormat,
-    IDirectDrawSurface4Impl_GetSurfaceDesc,
-    IDirectDrawSurface4Impl_Initialize,
-    IDirectDrawSurface4Impl_IsLost,
-    IDirectDrawSurface4Impl_Lock,
-    IDirectDrawSurface4Impl_ReleaseDC,
-    IDirectDrawSurface4Impl_Restore,
-    IDirectDrawSurface4Impl_SetClipper,
-    IDirectDrawSurface4Impl_SetColorKey,
-    IDirectDrawSurface4Impl_SetOverlayPosition,
-    DGA2_IDirectDrawSurface4Impl_SetPalette,
-    DGA_IDirectDrawSurface4Impl_Unlock,
-    IDirectDrawSurface4Impl_UpdateOverlay,
-    IDirectDrawSurface4Impl_UpdateOverlayDisplay,
-    IDirectDrawSurface4Impl_UpdateOverlayZOrder,
-    IDirectDrawSurface4Impl_GetDDInterface,
-    IDirectDrawSurface4Impl_PageLock,
-    IDirectDrawSurface4Impl_PageUnlock,
-    IDirectDrawSurface4Impl_SetSurfaceDesc,
-    IDirectDrawSurface4Impl_SetPrivateData,
-    IDirectDrawSurface4Impl_GetPrivateData,
-    IDirectDrawSurface4Impl_FreePrivateData,
-    IDirectDrawSurface4Impl_GetUniquenessValue,
-    IDirectDrawSurface4Impl_ChangeUniquenessValue
+    return XF86DGA2_DirectDrawSurface_Create(This->ddraw_owner,
+					     &This->surface_desc, ppDup, NULL);
+}
+
+void XF86DGA2_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				      IDirectDrawSurfaceImpl* back)
+{
+    XF86DGA2_PRIV_VAR(front_priv, front);
+    XF86DGA2_PRIV_VAR(back_priv, back);
+
+    {
+	DWORD tmp;
+	tmp = front_priv->xf86dga2.fb_vofs;
+	front_priv->xf86dga2.fb_vofs = back_priv->xf86dga2.fb_vofs;
+	back_priv->xf86dga2.fb_vofs = tmp;
+    }
+    {
+	LPVOID tmp;
+	tmp = front_priv->xf86dga2.fb_addr;
+	front_priv->xf86dga2.fb_addr = back_priv->xf86dga2.fb_addr;
+	back_priv->xf86dga2.fb_addr = tmp;
+    }
+
+    DIB_DirectDrawSurface_flip_data(front, back);
+}
+
+void XF86DGA2_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This)
+{
+    XF86DGA2_PRIV_VAR(priv, This);
+
+    /* XXX having the Flip's dwFlags would be nice here */
+    TSXDGASetViewport(display, DefaultScreen(display),
+		      0, priv->xf86dga2.fb_vofs, XDGAFlipImmediate);
+}
+
+HWND XF86DGA2_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
+{
+    /* there's a potential drawable in the ddraw object's current_mode->pixmap...
+     * perhaps it's possible to use it for the Direct3D rendering as well? */
+    return 0;
+}
+
+static ICOM_VTABLE(IDirectDrawSurface7) XF86DGA2_IDirectDrawSurface7_VTable =
+{
+    Main_DirectDrawSurface_QueryInterface,
+    Main_DirectDrawSurface_AddRef,
+    Main_DirectDrawSurface_Release,
+    Main_DirectDrawSurface_AddAttachedSurface,
+    Main_DirectDrawSurface_AddOverlayDirtyRect,
+    DIB_DirectDrawSurface_Blt,
+    Main_DirectDrawSurface_BltBatch,
+    DIB_DirectDrawSurface_BltFast,
+    Main_DirectDrawSurface_DeleteAttachedSurface,
+    Main_DirectDrawSurface_EnumAttachedSurfaces,
+    Main_DirectDrawSurface_EnumOverlayZOrders,
+    Main_DirectDrawSurface_Flip,
+    Main_DirectDrawSurface_GetAttachedSurface,
+    Main_DirectDrawSurface_GetBltStatus,
+    Main_DirectDrawSurface_GetCaps,
+    Main_DirectDrawSurface_GetClipper,
+    Main_DirectDrawSurface_GetColorKey,
+    Main_DirectDrawSurface_GetDC,
+    Main_DirectDrawSurface_GetFlipStatus,
+    Main_DirectDrawSurface_GetOverlayPosition,
+    Main_DirectDrawSurface_GetPalette,
+    Main_DirectDrawSurface_GetPixelFormat,
+    Main_DirectDrawSurface_GetSurfaceDesc,
+    Main_DirectDrawSurface_Initialize,
+    Main_DirectDrawSurface_IsLost,
+    Main_DirectDrawSurface_Lock,
+    Main_DirectDrawSurface_ReleaseDC,
+    DIB_DirectDrawSurface_Restore,
+    Main_DirectDrawSurface_SetClipper,
+    Main_DirectDrawSurface_SetColorKey,
+    Main_DirectDrawSurface_SetOverlayPosition,
+    Main_DirectDrawSurface_SetPalette,
+    Main_DirectDrawSurface_Unlock,
+    Main_DirectDrawSurface_UpdateOverlay,
+    Main_DirectDrawSurface_UpdateOverlayDisplay,
+    Main_DirectDrawSurface_UpdateOverlayZOrder,
+    Main_DirectDrawSurface_GetDDInterface,
+    Main_DirectDrawSurface_PageLock,
+    Main_DirectDrawSurface_PageUnlock,
+    DIB_DirectDrawSurface_SetSurfaceDesc,
+    Main_DirectDrawSurface_SetPrivateData,
+    Main_DirectDrawSurface_GetPrivateData,
+    Main_DirectDrawSurface_FreePrivateData,
+    Main_DirectDrawSurface_GetUniquenessValue,
+    Main_DirectDrawSurface_ChangeUniquenessValue,
+    Main_DirectDrawSurface_SetPriority,
+    Main_DirectDrawSurface_GetPriority,
+    Main_DirectDrawSurface_SetLOD,
+    Main_DirectDrawSurface_GetLOD
 };
+
+#endif /* HAVE_LIBXXF86DGA2 */
diff --git a/dlls/ddraw/dsurface/dga2.h b/dlls/ddraw/dsurface/dga2.h
new file mode 100644
index 0000000..23f8f0d
--- /dev/null
+++ b/dlls/ddraw/dsurface/dga2.h
@@ -0,0 +1,50 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_DGA2_H_INCLUDED
+#define DDRAW_DSURFACE_DGA2_H_INCLUDED
+
+#define XF86DGA2_PRIV(surf) ((XF86DGA2_DirectDrawSurfaceImpl*)((surf)->private))
+
+#define XF86DGA2_PRIV_VAR(name,surf) \
+	XF86DGA2_DirectDrawSurfaceImpl* name = XF86DGA2_PRIV(surf)
+
+struct XF86DGA2_DirectDrawSurfaceImpl_Part
+{
+    LPVOID fb_addr;
+    DWORD fb_pitch, fb_vofs;
+    Colormap pal;
+};
+
+typedef struct
+{
+    struct DIB_DirectDrawSurfaceImpl_Part dib;
+    struct XF86DGA2_DirectDrawSurfaceImpl_Part xf86dga2;
+} XF86DGA2_DirectDrawSurfaceImpl;
+
+HRESULT
+XF86DGA2_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				     IDirectDrawImpl* pDD,
+				     const DDSURFACEDESC2* pDDSD);
+
+HRESULT
+XF86DGA2_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+				  const DDSURFACEDESC2 *pDDSD,
+				  LPDIRECTDRAWSURFACE7 *ppSurf,
+				  IUnknown *pUnkOuter);
+
+void XF86DGA2_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This);
+
+void XF86DGA2_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+					    IDirectDrawPaletteImpl* pal);
+void XF86DGA2_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+					       IDirectDrawPaletteImpl* pal,
+					       DWORD dwStart, DWORD dwCount,
+					       LPPALETTEENTRY palent);
+HRESULT XF86DGA2_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						 LPDIRECTDRAWSURFACE7* ppDup);
+void XF86DGA2_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+					  IDirectDrawSurfaceImpl* back);
+void XF86DGA2_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This);
+HWND XF86DGA2_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This);
+
+#endif
diff --git a/dlls/ddraw/dsurface/dib.c b/dlls/ddraw/dsurface/dib.c
new file mode 100644
index 0000000..285f66d
--- /dev/null
+++ b/dlls/ddraw/dsurface/dib.c
@@ -0,0 +1,879 @@
+/*		DIBSection DirectDrawSurface driver
+ *
+ * Copyright 1997-2000 Marcus Meissner
+ * Copyright 1998-2000 Lionel Ulmer
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+#include "winerror.h"
+#include "bitmap.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "debugtools.h"
+#include "ddraw_private.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static ICOM_VTABLE(IDirectDrawSurface7) DIB_IDirectDrawSurface7_VTable;
+
+static HRESULT create_dib(IDirectDrawSurfaceImpl* This)
+{
+    BITMAPINFO* b_info;
+    UINT usage;
+    HDC ddc;
+    DIB_DirectDrawSurfaceImpl* priv = This->private;
+
+    assert(This->surface_desc.lpSurface != NULL);
+
+    switch (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount)
+    {
+    case 16:
+    case 32:
+	/* Allocate extra space to store the RGB bit masks. */
+	b_info = (BITMAPINFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+					sizeof(BITMAPINFOHEADER)
+					+ 3 * sizeof(DWORD));
+	break;
+
+    case 24:
+	b_info = (BITMAPINFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+					sizeof(BITMAPINFOHEADER));
+	break;
+
+    default:
+	/* Allocate extra space for a palette. */
+	b_info = (BITMAPINFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+					sizeof(BITMAPINFOHEADER)
+					+ sizeof(RGBQUAD)
+					* (1 << This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount));
+	break;
+    }
+
+    b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    b_info->bmiHeader.biWidth = This->surface_desc.dwWidth;
+    b_info->bmiHeader.biHeight = -This->surface_desc.dwHeight;
+    b_info->bmiHeader.biPlanes = 1;
+    b_info->bmiHeader.biBitCount = This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount;
+
+    if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount != 16)
+	&& (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount != 32))
+        b_info->bmiHeader.biCompression = BI_RGB;
+    else
+        b_info->bmiHeader.biCompression = BI_BITFIELDS;
+
+    b_info->bmiHeader.biSizeImage
+	= (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8)
+	* This->surface_desc.dwWidth * This->surface_desc.dwHeight;
+
+    b_info->bmiHeader.biXPelsPerMeter = 0;
+    b_info->bmiHeader.biYPelsPerMeter = 0;
+    b_info->bmiHeader.biClrUsed = 0;
+    b_info->bmiHeader.biClrImportant = 0;
+
+    switch (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount)
+    {
+    case 16:
+    case 32:
+    {
+	DWORD *masks = (DWORD *) &(b_info->bmiColors);
+
+	usage = 0;
+	masks[0] = This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask;
+	masks[1] = This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask;
+	masks[2] = This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask;
+    }
+    break;
+
+    case 24:
+	/* Nothing to do */
+	usage = DIB_RGB_COLORS;
+	break;
+
+    default:
+	/* Don't know palette */
+	usage = 0;
+	break;
+    }
+
+    ddc = CreateDCA("DISPLAY", NULL, NULL, NULL);
+    if (ddc == 0)
+    {
+	HeapFree(GetProcessHeap(), 0, b_info);
+	return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    priv->dib.DIBsection
+	= DIB_CreateDIBSection(ddc, b_info, usage, &(priv->dib.bitmap_data), 0,
+			       (DWORD)This->surface_desc.lpSurface,
+			       This->surface_desc.u1.lPitch);
+    DeleteDC(ddc);
+    if (!priv->dib.DIBsection) {
+	ERR("CreateDIBSection failed!\n");
+	HeapFree(GetProcessHeap(), 0, b_info);
+	return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    TRACE("DIBSection at : %p\n", priv->dib.bitmap_data);
+    if (!This->surface_desc.u1.lPitch) {
+	/* This can't happen, right? */
+	/* or use GDI_GetObj to get it from the created DIB? */
+	This->surface_desc.u1.lPitch = DIB_GetDIBWidthBytes(b_info->bmiHeader.biWidth, b_info->bmiHeader.biBitCount);
+	This->surface_desc.dwFlags |= DDSD_PITCH;
+    }
+
+    if (!This->surface_desc.lpSurface) {
+	This->surface_desc.lpSurface = priv->dib.bitmap_data;
+	This->surface_desc.dwFlags |= DDSD_LPSURFACE;
+    }
+
+    HeapFree(GetProcessHeap(), 0, b_info);
+
+    /* I don't think it's worth checking for this. */
+    if (priv->dib.bitmap_data != This->surface_desc.lpSurface)
+	ERR("unexpected error creating DirectDrawSurface DIB section\n");
+
+    return S_OK;
+}
+
+void DIB_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
+{
+    DIB_DirectDrawSurfaceImpl* priv = This->private;
+
+    DeleteObject(priv->dib.DIBsection);
+
+    if (!priv->dib.client_memory)
+	VirtualFree(This->surface_desc.lpSurface, 0, MEM_RELEASE);
+
+    Main_DirectDrawSurface_final_release(This);
+}
+
+HRESULT DIB_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						LPDIRECTDRAWSURFACE7* ppDup)
+{
+    return DIB_DirectDrawSurface_Create(This->ddraw_owner,
+					&This->surface_desc, ppDup, NULL);
+}
+
+HRESULT DIB_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
+					IDirectDrawImpl *pDD,
+					const DDSURFACEDESC2 *pDDSD)
+{
+    HRESULT hr;
+    DIB_DirectDrawSurfaceImpl* priv = This->private;
+
+    TRACE("(%p)->(%p,%p)\n",This,pDD,pDDSD);
+    hr = Main_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr)) return hr;
+
+    ICOM_INIT_INTERFACE(This, IDirectDrawSurface7,
+			DIB_IDirectDrawSurface7_VTable);
+
+    This->final_release = DIB_DirectDrawSurface_final_release;
+    This->duplicate_surface = DIB_DirectDrawSurface_duplicate_surface;
+    This->flip_data = DIB_DirectDrawSurface_flip_data;
+
+    This->get_dc     = DIB_DirectDrawSurface_get_dc;
+    This->release_dc = DIB_DirectDrawSurface_release_dc;
+    This->hDC = (HDC)NULL;
+
+    This->set_palette    = DIB_DirectDrawSurface_set_palette;
+    This->update_palette = DIB_DirectDrawSurface_update_palette;
+
+    TRACE("(%ldx%ld, pitch=%ld)\n",
+	  This->surface_desc.dwWidth, This->surface_desc.dwHeight,
+	  This->surface_desc.u1.lPitch);
+    /* XXX load dwWidth and dwHeight from pDD if they are not specified? */
+
+    if (This->surface_desc.dwFlags & DDSD_LPSURFACE)
+    {
+	/* "Client memory": it is managed by the application. */
+	/* XXX What if lPitch is not set? Use dwWidth or fail? */
+
+	priv->dib.client_memory = TRUE;
+    }
+    else
+    {
+	if (!(This->surface_desc.dwFlags & DDSD_PITCH))
+	{
+	    int pitch = This->surface_desc.u1.lPitch;
+	    if (pitch % 8 != 0)
+		pitch += 8 - (pitch % 8);
+	}
+	/* XXX else: how should lPitch be verified? */
+
+	This->surface_desc.dwFlags |= DDSD_PITCH|DDSD_LPSURFACE;
+
+	This->surface_desc.lpSurface
+	    = VirtualAlloc(NULL, This->surface_desc.u1.lPitch
+			   * This->surface_desc.dwHeight,
+			   MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+
+	if (This->surface_desc.lpSurface == NULL)
+	{
+	    Main_DirectDrawSurface_final_release(This);
+	    return HRESULT_FROM_WIN32(GetLastError());
+	}
+
+	priv->dib.client_memory = FALSE;
+    }
+
+    hr = create_dib(This);
+    if (FAILED(hr))
+    {
+	if (!priv->dib.client_memory)
+	    VirtualFree(This->surface_desc.lpSurface, 0, MEM_RELEASE);
+
+	Main_DirectDrawSurface_final_release(This);
+
+	return hr;
+    }
+
+    return DD_OK;
+}
+
+/* Not an API */
+HRESULT DIB_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+				     const DDSURFACEDESC2 *pDDSD,
+				     LPDIRECTDRAWSURFACE7 *ppSurf,
+				     IUnknown *pUnkOuter)
+{
+    IDirectDrawSurfaceImpl* This;
+    HRESULT hr;
+    assert(pUnkOuter == NULL);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(*This) + sizeof(DIB_DirectDrawSurfaceImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    This->private = (DIB_DirectDrawSurfaceImpl*)(This+1);
+
+    hr = DIB_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7);
+
+    return hr;
+
+}
+
+/* AddAttachedSurface: generic */
+/* AddOverlayDirtyRect: generic, unimplemented */
+
+static HRESULT _Blt_ColorFill(
+    LPBYTE buf, int width, int height, int bpp, LONG lPitch, DWORD color
+) {
+    int x, y;
+    LPBYTE first;
+
+    /* Do first row */
+
+#define COLORFILL_ROW(type) { \
+    type *d = (type *) buf; \
+    for (x = 0; x < width; x++) \
+	d[x] = (type) color; \
+    break; \
+}
+
+    switch(bpp) {
+    case 1: COLORFILL_ROW(BYTE)
+    case 2: COLORFILL_ROW(WORD)
+    case 4: COLORFILL_ROW(DWORD)
+    default:
+	FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
+	return DDERR_UNSUPPORTED;
+    }
+
+#undef COLORFILL_ROW
+
+    /* Now copy first row */
+    first = buf;
+    for (y = 1; y < height; y++) {
+	buf += lPitch;
+	memcpy(buf, first, width * bpp);
+    }
+    return DD_OK;
+}
+
+HRESULT WINAPI
+DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
+			  LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
+			  DWORD dwFlags, LPDDBLTFX lpbltfx)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl,iface);
+    RECT		xdst,xsrc;
+    DDSURFACEDESC2	ddesc,sdesc;
+    HRESULT		ret = DD_OK;
+    int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
+    int x, y;
+    LPBYTE dbuf, sbuf;
+
+    TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
+
+    DD_STRUCT_INIT(&ddesc);
+    DD_STRUCT_INIT(&sdesc);
+
+    sdesc.dwSize = sizeof(sdesc);
+    if (src) IDirectDrawSurface7_Lock(src, NULL, &sdesc, 0, 0);
+    ddesc.dwSize = sizeof(ddesc);
+    IDirectDrawSurface7_Lock(iface,NULL,&ddesc,0,0);
+
+    if (TRACE_ON(ddraw)) {
+	if (rdst) TRACE("\tdestrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
+	if (rsrc) TRACE("\tsrcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
+	TRACE("\tflags: ");
+	DDRAW_dump_DDBLT(dwFlags);
+	if (dwFlags & DDBLT_DDFX) {
+	    TRACE("\tblitfx: ");
+	    DDRAW_dump_DDBLTFX(lpbltfx->dwDDFX);
+	}
+    }
+
+    if (rdst) {
+	if ((rdst->top < 0) ||
+	    (rdst->left < 0) ||
+	    (rdst->bottom < 0) ||
+	    (rdst->right < 0)) {
+	  ERR(" Negative values in LPRECT !!!\n");
+	  goto release;
+	}
+	memcpy(&xdst,rdst,sizeof(xdst));
+    } else {
+	xdst.top	= 0;
+	xdst.bottom	= ddesc.dwHeight;
+	xdst.left	= 0;
+	xdst.right	= ddesc.dwWidth;
+    }
+
+    if (rsrc) {
+	if ((rsrc->top < 0) ||
+	    (rsrc->left < 0) ||
+	    (rsrc->bottom < 0) ||
+	    (rsrc->right < 0)) {
+	  ERR(" Negative values in LPRECT !!!\n");
+	  goto release;
+	}
+	memcpy(&xsrc,rsrc,sizeof(xsrc));
+    } else {
+	if (src) {
+	    xsrc.top	= 0;
+	    xsrc.bottom	= sdesc.dwHeight;
+	    xsrc.left	= 0;
+	    xsrc.right	= sdesc.dwWidth;
+	} else {
+	    memset(&xsrc,0,sizeof(xsrc));
+	}
+    }
+    if (src) assert((xsrc.bottom-xsrc.top) <= sdesc.dwHeight);
+    assert((xdst.bottom-xdst.top) <= ddesc.dwHeight);
+
+    bpp = GET_BPP(ddesc);
+    srcheight = xsrc.bottom - xsrc.top;
+    srcwidth = xsrc.right - xsrc.left;
+    dstheight = xdst.bottom - xdst.top;
+    dstwidth = xdst.right - xdst.left;
+    width = (xdst.right - xdst.left) * bpp;
+
+    assert(width <= ddesc.u1.lPitch);
+
+    dbuf = (BYTE*)ddesc.lpSurface+(xdst.top*ddesc.u1.lPitch)+(xdst.left*bpp);
+
+    dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
+
+    /* First, all the 'source-less' blits */
+    if (dwFlags & DDBLT_COLORFILL) {
+	ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
+			     ddesc.u1.lPitch, lpbltfx->u5.dwFillColor);
+	dwFlags &= ~DDBLT_COLORFILL;
+    }
+
+    if (dwFlags & DDBLT_DEPTHFILL)
+	FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
+    if (dwFlags & DDBLT_ROP) {
+	/* Catch some degenerate cases here */
+	switch(lpbltfx->dwROP) {
+	case BLACKNESS:
+	    ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.u1.lPitch,0);
+	    break;
+	case 0xAA0029: /* No-op */
+	    break;
+	case WHITENESS:
+	    ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.u1.lPitch,~0);
+	    break;
+	case SRCCOPY: /* well, we do that below ? */
+	    break;
+	default: 
+	    FIXME("Unsupported raster op: %08lx  Pattern: %p\n", lpbltfx->dwROP, lpbltfx->u5.lpDDSPattern);
+	    goto error;
+	}
+	dwFlags &= ~DDBLT_ROP;
+    }
+    if (dwFlags & DDBLT_DDROPS) {
+	FIXME("\tDdraw Raster Ops: %08lx  Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u5.lpDDSPattern);
+    }
+    /* Now the 'with source' blits */
+    if (src) {
+	LPBYTE sbase;
+	int sx, xinc, sy, yinc;
+
+	if (!dstwidth || !dstheight) /* hmm... stupid program ? */
+	    goto release;
+	sbase = (BYTE*)sdesc.lpSurface+(xsrc.top*sdesc.u1.lPitch)+xsrc.left*bpp;
+	xinc = (srcwidth << 16) / dstwidth;
+	yinc = (srcheight << 16) / dstheight;
+
+	if (!dwFlags) {
+	    /* No effects, we can cheat here */
+	    if (dstwidth == srcwidth) {
+		if (dstheight == srcheight) {
+		    /* No stretching in either direction. This needs to be as
+		     * fast as possible */
+		    sbuf = sbase;
+		    for (y = 0; y < dstheight; y++) {
+			memcpy(dbuf, sbuf, width);
+			sbuf += sdesc.u1.lPitch;
+			dbuf += ddesc.u1.lPitch;
+		    }
+		} else {
+		    /* Stretching in Y direction only */
+		    for (y = sy = 0; y < dstheight; y++, sy += yinc) {
+			sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
+			memcpy(dbuf, sbuf, width);
+			dbuf += ddesc.u1.lPitch;
+		    }
+		}
+	    } else {
+		/* Stretching in X direction */
+		int last_sy = -1;
+		for (y = sy = 0; y < dstheight; y++, sy += yinc) {
+		    sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
+
+		    if ((sy >> 16) == (last_sy >> 16)) {
+			/* this sourcerow is the same as last sourcerow -
+			 * copy already stretched row
+			 */
+			memcpy(dbuf, dbuf - ddesc.u1.lPitch, width);
+		    } else {
+#define STRETCH_ROW(type) { \
+		    type *s = (type *) sbuf, *d = (type *) dbuf; \
+		    for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
+		    d[x] = s[sx >> 16]; \
+		    break; }
+
+		    switch(bpp) {
+		    case 1: STRETCH_ROW(BYTE)
+		    case 2: STRETCH_ROW(WORD)
+		    case 4: STRETCH_ROW(DWORD)
+		    case 3: {
+			LPBYTE s,d = dbuf;
+			for (x = sx = 0; x < dstwidth; x++, sx+= xinc) {
+			    DWORD pixel;
+
+			    s = sbuf+3*(sx>>16);
+			    pixel = (s[0]<<16)|(s[1]<<8)|s[2];
+			    d[0] = (pixel>>16)&0xff;
+			    d[1] = (pixel>> 8)&0xff;
+			    d[2] = (pixel    )&0xff;
+			    d+=3;
+			}
+			break;
+		    }
+		    default:
+			FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
+			ret = DDERR_UNSUPPORTED;
+			goto error;
+		    }
+#undef STRETCH_ROW
+		    }
+		    dbuf += ddesc.u1.lPitch;
+		    last_sy = sy;
+		}
+	    }
+	} else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST)) {
+	    DWORD keylow, keyhigh;
+
+	    if (dwFlags & DDBLT_KEYSRC) {
+		keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
+		keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
+	    } else {
+		/* I'm not sure if this is correct */
+		FIXME("DDBLT_KEYDEST not fully supported yet.\n");
+		keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
+		keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
+	    }
+
+
+	    for (y = sy = 0; y < dstheight; y++, sy += yinc) {
+		sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
+
+#define COPYROW_COLORKEY(type) { \
+		type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
+		for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
+		    tmp = s[sx >> 16]; \
+		    if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
+		} \
+		break; }
+
+		switch (bpp) {
+		case 1: COPYROW_COLORKEY(BYTE)
+		case 2: COPYROW_COLORKEY(WORD)
+		case 4: COPYROW_COLORKEY(DWORD)
+		default:
+		    FIXME("%s color-keyed blit not implemented for bpp %d!\n",
+		    (dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
+		    ret = DDERR_UNSUPPORTED;
+		    goto error;
+		}
+		dbuf += ddesc.u1.lPitch;
+	    }
+#undef COPYROW_COLORKEY
+	    dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST);
+	}
+    }
+
+error:
+    if (dwFlags && FIXME_ON(ddraw)) {
+	FIXME("\tUnsupported flags: ");
+	DDRAW_dump_DDBLT(dwFlags);
+    }
+
+release:
+    IDirectDrawSurface7_Unlock(iface,NULL);
+    if (src) IDirectDrawSurface7_Unlock(src,NULL);
+    return DD_OK;
+}
+
+/* BltBatch: generic, unimplemented */
+
+HRESULT WINAPI
+DIB_DirectDrawSurface_BltFast(LPDIRECTDRAWSURFACE7 iface, DWORD dstx,
+			      DWORD dsty, LPDIRECTDRAWSURFACE7 src,
+			      LPRECT rsrc, DWORD trans)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl,iface);
+    int			bpp, w, h, x, y;
+    DDSURFACEDESC2	ddesc,sdesc;
+    HRESULT		ret = DD_OK;
+    LPBYTE		sbuf, dbuf;
+    RECT		rsrc2;
+
+
+    if (TRACE_ON(ddraw)) {
+	FIXME("(%p)->(%ld,%ld,%p,%p,%08lx)\n",
+		This,dstx,dsty,src,rsrc,trans
+	);
+	FIXME("	trans:");
+	if (FIXME_ON(ddraw))
+	  DDRAW_dump_DDBLTFAST(trans);
+	if (rsrc)
+	  FIXME("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
+	else
+	  FIXME(" srcrect: NULL\n");
+    }
+    
+    /* We need to lock the surfaces, or we won't get refreshes when done. */
+    sdesc.dwSize = sizeof(sdesc);
+    IDirectDrawSurface7_Lock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
+    ddesc.dwSize = sizeof(ddesc);
+    IDirectDrawSurface7_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
+
+   if (!rsrc) {
+	   WARN("rsrc is NULL!\n");
+	   rsrc = &rsrc2;
+	   rsrc->left = rsrc->top = 0;
+	   rsrc->right = sdesc.dwWidth;
+	   rsrc->bottom = sdesc.dwHeight;
+   }
+
+    bpp = GET_BPP(This->surface_desc);
+    sbuf = (BYTE *)sdesc.lpSurface+(rsrc->top*sdesc.u1.lPitch)+rsrc->left*bpp;
+    dbuf = (BYTE *)ddesc.lpSurface+(dsty*ddesc.u1.lPitch)+dstx* bpp;
+
+
+    h=rsrc->bottom-rsrc->top;
+    if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
+    if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
+    if (h<0) h=0;
+
+    w=rsrc->right-rsrc->left;
+    if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
+    if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
+    if (w<0) w=0;
+
+    if (trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) {
+	DWORD keylow, keyhigh;
+	if (trans & DDBLTFAST_SRCCOLORKEY) {
+	    keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
+	    keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
+	} else {
+	    /* I'm not sure if this is correct */
+	    FIXME("DDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
+	    keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
+	    keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
+	}
+
+#define COPYBOX_COLORKEY(type) { \
+    type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
+    s = (type *) ((BYTE *) sdesc.lpSurface + (rsrc->top * sdesc.u1.lPitch) + rsrc->left * bpp); \
+    d = (type *) ((BYTE *) ddesc.lpSurface + (dsty * ddesc.u1.lPitch) + dstx * bpp); \
+    for (y = 0; y < h; y++) { \
+	for (x = 0; x < w; x++) { \
+	    tmp = s[x]; \
+	    if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
+	} \
+	(LPBYTE)s += sdesc.u1.lPitch; \
+	(LPBYTE)d += ddesc.u1.lPitch; \
+    } \
+    break; \
+}
+
+	switch (bpp) {
+	case 1: COPYBOX_COLORKEY(BYTE)
+	case 2: COPYBOX_COLORKEY(WORD)
+	case 4: COPYBOX_COLORKEY(DWORD)
+	default:
+	    FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
+	    ret = DDERR_UNSUPPORTED;
+	    goto error;
+	}
+#undef COPYBOX_COLORKEY
+    } else {
+	int width = w * bpp;
+
+	for (y = 0; y < h; y++) {
+	    memcpy(dbuf, sbuf, width);
+	    sbuf += sdesc.u1.lPitch;
+	    dbuf += ddesc.u1.lPitch;
+	}
+    }
+error:
+    IDirectDrawSurface7_Unlock(iface, NULL);
+    IDirectDrawSurface7_Unlock(src, NULL);
+    return ret;
+}
+
+/* ChangeUniquenessValue: generic */
+/* DeleteAttachedSurface: generic */
+/* EnumAttachedSurfaces: generic */
+/* EnumOverlayZOrders: generic, unimplemented */
+
+void DIB_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				     IDirectDrawSurfaceImpl* back)
+{
+    DIB_DirectDrawSurfaceImpl* front_priv = front->private;
+    DIB_DirectDrawSurfaceImpl* back_priv = back->private;
+
+    TRACE("(%p,%p)\n",front,back);
+    Main_DirectDrawSurface_flip_data(front, back);
+
+    {
+	HBITMAP tmp;
+	tmp = front_priv->dib.DIBsection;
+	front_priv->dib.DIBsection = back_priv->dib.DIBsection;
+	back_priv->dib.DIBsection = tmp;
+    }
+
+    {
+	void* tmp;
+	tmp = front_priv->dib.bitmap_data;
+	front_priv->dib.bitmap_data = back_priv->dib.bitmap_data;
+	back_priv->dib.bitmap_data = tmp;
+
+	tmp = front->surface_desc.lpSurface;
+	front->surface_desc.lpSurface = back->surface_desc.lpSurface;
+	back->surface_desc.lpSurface = tmp;
+    }
+
+    /* client_memory should not be different, but just in case */
+    {
+	BOOL tmp;
+	tmp = front_priv->dib.client_memory;
+	front_priv->dib.client_memory = back_priv->dib.client_memory;
+	back_priv->dib.client_memory = tmp;
+    }
+}
+
+/* Flip: generic */
+/* FreePrivateData: generic */
+/* GetAttachedSurface: generic */
+/* GetBltStatus: generic */
+/* GetCaps: generic (Returns the caps from This->surface_desc.) */
+/* GetClipper: generic */
+/* GetColorKey: generic */
+
+HRESULT DIB_DirectDrawSurface_alloc_dc(IDirectDrawSurfaceImpl* This, HDC* phDC)
+{
+    DIB_PRIV_VAR(priv, This);
+    HDC hDC;
+
+    TRACE("Grabbing a DC for surface: %p\n", This);
+
+    hDC = CreateCompatibleDC(0);
+    priv->dib.holdbitmap = SelectObject(hDC, priv->dib.DIBsection);
+    if (This->palette)
+	SelectPalette(hDC, This->palette->hpal, FALSE);
+
+    *phDC = hDC;
+
+    return S_OK;
+}
+
+HRESULT DIB_DirectDrawSurface_free_dc(IDirectDrawSurfaceImpl* This, HDC hDC)
+{
+    DIB_PRIV_VAR(priv, This);
+
+    TRACE("Releasing DC for surface: %p\n", This);
+
+    SelectObject(hDC, priv->dib.holdbitmap);
+    DeleteDC(hDC);
+
+    return S_OK;
+}
+
+HRESULT DIB_DirectDrawSurface_get_dc(IDirectDrawSurfaceImpl* This, HDC* phDC)
+{
+    return DIB_DirectDrawSurface_alloc_dc(This, phDC);
+}
+
+HRESULT DIB_DirectDrawSurface_release_dc(IDirectDrawSurfaceImpl* This, HDC hDC)
+{
+    return DIB_DirectDrawSurface_free_dc(This, hDC);
+}
+
+/* GetDDInterface: generic */
+/* GetFlipStatus: generic */
+/* GetLOD: generic */
+/* GetOverlayPosition: generic */
+/* GetPalette: generic */
+/* GetPixelFormat: generic */
+/* GetPriority: generic */
+/* GetPrivateData: generic */
+/* GetSurfaceDesc: generic */
+/* GetUniquenessValue: generic */
+/* Initialize: generic */
+/* IsLost: generic */
+/* Lock: generic with callback? */
+/* PageLock: generic */
+/* PageUnlock: generic */
+
+HRESULT WINAPI
+DIB_DirectDrawSurface_Restore(LPDIRECTDRAWSURFACE7 iface)
+{
+    TRACE("(%p)\n",iface);
+    return DD_OK;	/* ??? */
+}
+
+/* SetClipper: generic */
+/* SetColorKey: generic */
+/* SetLOD: generic */
+/* SetOverlayPosition: generic */
+
+void DIB_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+				       IDirectDrawPaletteImpl* pal) 
+{
+    if (!pal) return;
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+	This->update_palette(This, pal,
+			     0, pal->palNumEntries,
+			     pal->palents);
+}
+
+void DIB_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+					  IDirectDrawPaletteImpl* pal,
+					  DWORD dwStart, DWORD dwCount,
+					  LPPALETTEENTRY palent)
+{
+    RGBQUAD col[256];
+    int n;
+    HDC dc;
+
+    TRACE("updating primary palette\n");
+    for (n=0; n<dwCount; n++) {
+      col[n].rgbRed   = palent[n].peRed;
+      col[n].rgbGreen = palent[n].peGreen;
+      col[n].rgbBlue  = palent[n].peBlue;
+      col[n].rgbReserved = 0;
+    }
+    This->get_dc(This, &dc);
+    SetDIBColorTable(dc, dwStart, dwCount, col);
+    This->release_dc(This, dc);
+    /* FIXME: propagate change to backbuffers */
+}
+
+
+/* SetPalette: generic */
+/* SetPriority: generic */
+/* SetPrivateData: generic */
+
+HRESULT WINAPI
+DIB_DirectDrawSurface_SetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
+				     LPDDSURFACEDESC2 pDDSD, DWORD dwFlags)
+{
+    /* XXX */
+    FIXME("(%p)->(%p,%08lx)\n",iface,pDDSD,dwFlags);
+    abort();
+    return E_FAIL;
+}
+
+/* Unlock: ???, need callback */
+/* UpdateOverlay: generic */
+/* UpdateOverlayDisplay: generic */
+/* UpdateOverlayZOrder: generic */
+
+static ICOM_VTABLE(IDirectDrawSurface7) DIB_IDirectDrawSurface7_VTable =
+{
+    Main_DirectDrawSurface_QueryInterface,
+    Main_DirectDrawSurface_AddRef,
+    Main_DirectDrawSurface_Release,
+    Main_DirectDrawSurface_AddAttachedSurface,
+    Main_DirectDrawSurface_AddOverlayDirtyRect,
+    DIB_DirectDrawSurface_Blt,
+    Main_DirectDrawSurface_BltBatch,
+    DIB_DirectDrawSurface_BltFast,
+    Main_DirectDrawSurface_DeleteAttachedSurface,
+    Main_DirectDrawSurface_EnumAttachedSurfaces,
+    Main_DirectDrawSurface_EnumOverlayZOrders,
+    Main_DirectDrawSurface_Flip,
+    Main_DirectDrawSurface_GetAttachedSurface,
+    Main_DirectDrawSurface_GetBltStatus,
+    Main_DirectDrawSurface_GetCaps,
+    Main_DirectDrawSurface_GetClipper,
+    Main_DirectDrawSurface_GetColorKey,
+    Main_DirectDrawSurface_GetDC,
+    Main_DirectDrawSurface_GetFlipStatus,
+    Main_DirectDrawSurface_GetOverlayPosition,
+    Main_DirectDrawSurface_GetPalette,
+    Main_DirectDrawSurface_GetPixelFormat,
+    Main_DirectDrawSurface_GetSurfaceDesc,
+    Main_DirectDrawSurface_Initialize,
+    Main_DirectDrawSurface_IsLost,
+    Main_DirectDrawSurface_Lock,
+    Main_DirectDrawSurface_ReleaseDC,
+    DIB_DirectDrawSurface_Restore,
+    Main_DirectDrawSurface_SetClipper,
+    Main_DirectDrawSurface_SetColorKey,
+    Main_DirectDrawSurface_SetOverlayPosition,
+    Main_DirectDrawSurface_SetPalette,
+    Main_DirectDrawSurface_Unlock,
+    Main_DirectDrawSurface_UpdateOverlay,
+    Main_DirectDrawSurface_UpdateOverlayDisplay,
+    Main_DirectDrawSurface_UpdateOverlayZOrder,
+    Main_DirectDrawSurface_GetDDInterface,
+    Main_DirectDrawSurface_PageLock,
+    Main_DirectDrawSurface_PageUnlock,
+    DIB_DirectDrawSurface_SetSurfaceDesc,
+    Main_DirectDrawSurface_SetPrivateData,
+    Main_DirectDrawSurface_GetPrivateData,
+    Main_DirectDrawSurface_FreePrivateData,
+    Main_DirectDrawSurface_GetUniquenessValue,
+    Main_DirectDrawSurface_ChangeUniquenessValue,
+    Main_DirectDrawSurface_SetPriority,
+    Main_DirectDrawSurface_GetPriority,
+    Main_DirectDrawSurface_SetLOD,
+    Main_DirectDrawSurface_GetLOD
+};
diff --git a/dlls/ddraw/dsurface/dib.h b/dlls/ddraw/dsurface/dib.h
new file mode 100644
index 0000000..bfbad79
--- /dev/null
+++ b/dlls/ddraw/dsurface/dib.h
@@ -0,0 +1,67 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_DIB_H_INCLUDED
+#define DDRAW_DSURFACE_DIB_H_INCLUDED
+
+#define DIB_PRIV(surf) ((DIB_DirectDrawSurfaceImpl*)((surf)->private))
+
+#define DIB_PRIV_VAR(name, surf) \
+	DIB_DirectDrawSurfaceImpl* name = DIB_PRIV(surf)
+
+
+struct DIB_DirectDrawSurfaceImpl_Part
+{
+    HBITMAP DIBsection;
+    void* bitmap_data;
+    HGDIOBJ holdbitmap;
+    BOOL client_memory;
+    DWORD d3d_data[4]; /* room for Direct3D driver data */
+};
+
+typedef struct
+{
+    struct DIB_DirectDrawSurfaceImpl_Part dib;
+} DIB_DirectDrawSurfaceImpl;
+
+HRESULT
+DIB_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
+				IDirectDrawImpl *pDD,
+				const DDSURFACEDESC2 *pDDSD);
+HRESULT
+DIB_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+			     const DDSURFACEDESC2 *pDDSD,
+			     LPDIRECTDRAWSURFACE7 *ppSurf,
+			     IUnknown *pUnkOuter);
+
+void DIB_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This);
+void DIB_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				     IDirectDrawSurfaceImpl* back);
+
+void DIB_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+				       IDirectDrawPaletteImpl* pal);
+void DIB_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+					  IDirectDrawPaletteImpl* pal,
+					  DWORD dwStart, DWORD dwCount,
+					  LPPALETTEENTRY palent);
+
+HRESULT DIB_DirectDrawSurface_get_dc(IDirectDrawSurfaceImpl* This, HDC* phDC);
+HRESULT DIB_DirectDrawSurface_release_dc(IDirectDrawSurfaceImpl* This,HDC hDC);
+
+HRESULT DIB_DirectDrawSurface_alloc_dc(IDirectDrawSurfaceImpl* This,HDC* phDC);
+HRESULT DIB_DirectDrawSurface_free_dc(IDirectDrawSurfaceImpl* This, HDC hDC);
+
+
+HRESULT WINAPI
+DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT prcDest,
+			  LPDIRECTDRAWSURFACE7 pSrcSurf, LPRECT prcSrc,
+			  DWORD dwFlags, LPDDBLTFX pBltFx);
+HRESULT WINAPI
+DIB_DirectDrawSurface_BltFast(LPDIRECTDRAWSURFACE7 iface, DWORD dwX,
+			      DWORD dwY, LPDIRECTDRAWSURFACE7 pSrcSurf,
+			      LPRECT prcSrc, DWORD dwTrans);
+HRESULT WINAPI
+DIB_DirectDrawSurface_Restore(LPDIRECTDRAWSURFACE7 iface);
+HRESULT WINAPI
+DIB_DirectDrawSurface_SetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
+				     LPDDSURFACEDESC2 pDDSD, DWORD dwFlags);
+#endif
diff --git a/dlls/ddraw/dsurface/dibtexture.c b/dlls/ddraw/dsurface/dibtexture.c
new file mode 100644
index 0000000..011ea5f
--- /dev/null
+++ b/dlls/ddraw/dsurface/dibtexture.c
@@ -0,0 +1,133 @@
+/*		DIB Section Texture DirectDrawSurface Driver
+ *
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+#include "winerror.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "debugtools.h"
+#include "ddraw_private.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/dibtexture.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static ICOM_VTABLE(IDirectDrawSurface7) DIBTexture_IDirectDrawSurface7_VTable;
+
+HRESULT
+DIBTexture_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				       IDirectDrawImpl* pDD,
+				       const DDSURFACEDESC2* pDDSD)
+{
+    HRESULT hr;
+
+    hr = DIB_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr)) return hr;
+
+    ICOM_INIT_INTERFACE(This, IDirectDrawSurface7,
+			DIBTexture_IDirectDrawSurface7_VTable);
+
+    This->final_release = DIBTexture_DirectDrawSurface_final_release;
+    This->duplicate_surface = DIBTexture_DirectDrawSurface_duplicate_surface;
+
+    return S_OK;
+}
+
+HRESULT
+DIBTexture_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+				    const DDSURFACEDESC2 *pDDSD,
+				    LPDIRECTDRAWSURFACE7 *ppSurf,
+				    IUnknown *pUnkOuter)
+{
+    IDirectDrawSurfaceImpl* This;
+    HRESULT hr;
+
+    assert(pUnkOuter == NULL);
+    assert(pDDSD->ddsCaps.dwCaps & DDSCAPS_TEXTURE);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(*This) + sizeof(DIBTexture_DirectDrawSurfaceImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    This->private = (DIBTexture_DirectDrawSurfaceImpl*)(This+1);
+
+    hr = DIBTexture_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7);
+
+    return hr;
+}
+
+void DIBTexture_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
+{
+    DIB_DirectDrawSurface_final_release(This);
+}
+
+HRESULT
+DIBTexture_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+					       LPDIRECTDRAWSURFACE7* ppDup)
+{
+    return DIBTexture_DirectDrawSurface_Create(This->ddraw_owner,
+					       &This->surface_desc, ppDup,
+					       NULL);
+}
+
+static ICOM_VTABLE(IDirectDrawSurface7) DIBTexture_IDirectDrawSurface7_VTable =
+{
+    Main_DirectDrawSurface_QueryInterface,
+    Main_DirectDrawSurface_AddRef,
+    Main_DirectDrawSurface_Release,
+    Main_DirectDrawSurface_AddAttachedSurface,
+    Main_DirectDrawSurface_AddOverlayDirtyRect,
+    DIB_DirectDrawSurface_Blt,
+    Main_DirectDrawSurface_BltBatch,
+    DIB_DirectDrawSurface_BltFast,
+    Main_DirectDrawSurface_DeleteAttachedSurface,
+    Main_DirectDrawSurface_EnumAttachedSurfaces,
+    Main_DirectDrawSurface_EnumOverlayZOrders,
+    Main_DirectDrawSurface_Flip,
+    Main_DirectDrawSurface_GetAttachedSurface,
+    Main_DirectDrawSurface_GetBltStatus,
+    Main_DirectDrawSurface_GetCaps,
+    Main_DirectDrawSurface_GetClipper,
+    Main_DirectDrawSurface_GetColorKey,
+    Main_DirectDrawSurface_GetDC,
+    Main_DirectDrawSurface_GetFlipStatus,
+    Main_DirectDrawSurface_GetOverlayPosition,
+    Main_DirectDrawSurface_GetPalette,
+    Main_DirectDrawSurface_GetPixelFormat,
+    Main_DirectDrawSurface_GetSurfaceDesc,
+    Main_DirectDrawSurface_Initialize,
+    Main_DirectDrawSurface_IsLost,
+    Main_DirectDrawSurface_Lock,
+    Main_DirectDrawSurface_ReleaseDC,
+    DIB_DirectDrawSurface_Restore,
+    Main_DirectDrawSurface_SetClipper,
+    Main_DirectDrawSurface_SetColorKey,
+    Main_DirectDrawSurface_SetOverlayPosition,
+    Main_DirectDrawSurface_SetPalette,
+    Main_DirectDrawSurface_Unlock,
+    Main_DirectDrawSurface_UpdateOverlay,
+    Main_DirectDrawSurface_UpdateOverlayDisplay,
+    Main_DirectDrawSurface_UpdateOverlayZOrder,
+    Main_DirectDrawSurface_GetDDInterface,
+    Main_DirectDrawSurface_PageLock,
+    Main_DirectDrawSurface_PageUnlock,
+    DIB_DirectDrawSurface_SetSurfaceDesc,
+    Main_DirectDrawSurface_SetPrivateData,
+    Main_DirectDrawSurface_GetPrivateData,
+    Main_DirectDrawSurface_FreePrivateData,
+    Main_DirectDrawSurface_GetUniquenessValue,
+    Main_DirectDrawSurface_ChangeUniquenessValue,
+    Main_DirectDrawSurface_SetPriority,
+    Main_DirectDrawSurface_GetPriority,
+    Main_DirectDrawSurface_SetLOD,
+    Main_DirectDrawSurface_GetLOD
+};
diff --git a/dlls/ddraw/dsurface/dibtexture.h b/dlls/ddraw/dsurface/dibtexture.h
new file mode 100644
index 0000000..ac539c3
--- /dev/null
+++ b/dlls/ddraw/dsurface/dibtexture.h
@@ -0,0 +1,48 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_DIBTEXTURE_H_INCLUDED
+#define DDRAW_DSURFACE_DIBTEXTURE_H_INCLUDED
+
+#define DIBTEXTURE_PRIV(surf) \
+	((DIBTexture_DirectDrawSurfaceImpl*)(surf->private))
+
+#define DIBTEXTURE_PRIV_VAR(name,surf) \
+	DIBTexture_DirectDrawSurfaceImpl* name = DIBTEXTURE_PRIV(surf)
+
+/* We add a spot for 3D drivers to store some private data. A cleaner
+ * solution would be to use SetPrivateData, but it's much too slow. */
+union DIBTexture_data
+{
+    int i;
+    void* p;
+};
+
+struct DIBTexture_DirectDrawSurfaceImpl_Part
+{
+    union DIBTexture_data data;
+};
+
+typedef struct
+{
+    struct DIB_DirectDrawSurfaceImpl_Part dib;
+    struct DIBTexture_DirectDrawSurfaceImpl_Part dibtexture;
+} DIBTexture_DirectDrawSurfaceImpl;
+
+HRESULT
+DIBTexture_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				       IDirectDrawImpl* pDD,
+				       const DDSURFACEDESC2* pDDSD);
+
+HRESULT
+DIBTexture_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+				    const DDSURFACEDESC2 *pDDSD,
+				    LPDIRECTDRAWSURFACE7 *ppSurf,
+				    IUnknown *pUnkOuter);
+
+void DIBTexture_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This);
+
+HRESULT
+DIBTexture_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+					       LPDIRECTDRAWSURFACE7* ppDup);
+
+#endif
diff --git a/dlls/ddraw/dsurface/fakezbuffer.c b/dlls/ddraw/dsurface/fakezbuffer.c
new file mode 100644
index 0000000..dc2ebde
--- /dev/null
+++ b/dlls/ddraw/dsurface/fakezbuffer.c
@@ -0,0 +1,194 @@
+/*		DirectDraw/Direct3D Z-Buffer stand in
+ *
+ * Copyright 2000 TransGaming Technologies Inc.
+ *
+ * This class provides a DirectDrawSurface implementation that represents
+ * a Z-Buffer surface. However it does not store an image and does not
+ * support Lock/Unlock or GetDC. It is merely a placeholder required by the
+ * Direct3D architecture.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <ddraw.h>
+#include <d3d.h>
+
+#include "debugtools.h"
+
+#include "ddcomimpl.h"
+#include "ddraw_private.h"
+#include "dsurface/main.h"
+#include "dsurface/fakezbuffer.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static ICOM_VTABLE(IDirectDrawSurface7) FakeZBuffer_IDirectDrawSurface7_VTable;
+
+HRESULT FakeZBuffer_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
+						IDirectDrawImpl *pDD,
+						const DDSURFACEDESC2 *pDDSD)
+{
+    HRESULT hr;
+
+    assert(pDDSD->ddsCaps.dwCaps & DDSCAPS_ZBUFFER);
+
+    hr = Main_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr)) return hr;
+
+    ICOM_INIT_INTERFACE(This, IDirectDrawSurface7,
+			FakeZBuffer_IDirectDrawSurface7_VTable);
+
+    This->final_release = FakeZBuffer_DirectDrawSurface_final_release;
+    This->duplicate_surface = FakeZBuffer_DirectDrawSurface_duplicate_surface;
+
+    return DD_OK;
+}
+
+/* Not an API */
+HRESULT FakeZBuffer_DirectDrawSurface_Create(IDirectDrawImpl* pDD,
+					     const DDSURFACEDESC2* pDDSD,
+					     LPDIRECTDRAWSURFACE7* ppSurf,
+					     IUnknown* pUnkOuter)
+{
+    IDirectDrawSurfaceImpl* This;
+    HRESULT hr;
+    assert(pUnkOuter == NULL);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(*This)
+		     + sizeof(FakeZBuffer_DirectDrawSurfaceImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    This->private = (FakeZBuffer_DirectDrawSurfaceImpl*)(This+1);
+
+    hr = FakeZBuffer_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7);
+
+    return hr;
+}
+
+void
+FakeZBuffer_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
+{
+    return Main_DirectDrawSurface_final_release(This);
+}
+
+HRESULT
+FakeZBuffer_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						LPDIRECTDRAWSURFACE7* ppDup)
+{
+    return FakeZBuffer_DirectDrawSurface_Create(This->ddraw_owner,
+						&This->surface_desc, ppDup,
+						NULL);
+}
+
+/* put your breakpoint/abort call here */
+static HRESULT cant_do_that(const char *s)
+{
+    FIXME("attempt to %s fake z-buffer\n", s);
+    return DDERR_UNSUPPORTED;
+}
+
+HRESULT WINAPI
+FakeZBuffer_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
+				  LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
+				  DWORD dwFlags, LPDDBLTFX lpbltfx)
+{
+    return cant_do_that("blt to a");
+}
+
+HRESULT WINAPI
+FakeZBuffer_DirectDrawSurface_BltFast(LPDIRECTDRAWSURFACE7 iface, DWORD dstx,
+				      DWORD dsty, LPDIRECTDRAWSURFACE7 src,
+				      LPRECT rsrc, DWORD trans)
+{
+    return cant_do_that("bltfast to a");
+}
+
+HRESULT WINAPI
+FakeZBuffer_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
+{
+    return cant_do_that("get a DC for a");
+}
+
+HRESULT WINAPI
+FakeZBuffer_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
+{
+    return cant_do_that("release a DC for a");
+}
+
+HRESULT WINAPI
+FakeZBuffer_DirectDrawSurface_Restore(LPDIRECTDRAWSURFACE7 iface)
+{
+    return DD_OK;
+}
+
+HRESULT WINAPI
+FakeZBuffer_DirectDrawSurface_SetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
+					     LPDDSURFACEDESC2 pDDSD,
+					     DWORD dwFlags)
+{
+    /* XXX */
+    abort();
+    return E_FAIL;
+}
+
+
+static ICOM_VTABLE(IDirectDrawSurface7) FakeZBuffer_IDirectDrawSurface7_VTable=
+{
+    Main_DirectDrawSurface_QueryInterface,
+    Main_DirectDrawSurface_AddRef,
+    Main_DirectDrawSurface_Release,
+    Main_DirectDrawSurface_AddAttachedSurface,
+    Main_DirectDrawSurface_AddOverlayDirtyRect,
+    FakeZBuffer_DirectDrawSurface_Blt,
+    Main_DirectDrawSurface_BltBatch,
+    FakeZBuffer_DirectDrawSurface_BltFast,
+    Main_DirectDrawSurface_DeleteAttachedSurface,
+    Main_DirectDrawSurface_EnumAttachedSurfaces,
+    Main_DirectDrawSurface_EnumOverlayZOrders,
+    Main_DirectDrawSurface_Flip,
+    Main_DirectDrawSurface_GetAttachedSurface,
+    Main_DirectDrawSurface_GetBltStatus,
+    Main_DirectDrawSurface_GetCaps,
+    Main_DirectDrawSurface_GetClipper,
+    Main_DirectDrawSurface_GetColorKey,
+    FakeZBuffer_DirectDrawSurface_GetDC,
+    Main_DirectDrawSurface_GetFlipStatus,
+    Main_DirectDrawSurface_GetOverlayPosition,
+    Main_DirectDrawSurface_GetPalette,
+    Main_DirectDrawSurface_GetPixelFormat,
+    Main_DirectDrawSurface_GetSurfaceDesc,
+    Main_DirectDrawSurface_Initialize,
+    Main_DirectDrawSurface_IsLost,
+    Main_DirectDrawSurface_Lock,
+    FakeZBuffer_DirectDrawSurface_ReleaseDC,
+    FakeZBuffer_DirectDrawSurface_Restore,
+    Main_DirectDrawSurface_SetClipper,
+    Main_DirectDrawSurface_SetColorKey,
+    Main_DirectDrawSurface_SetOverlayPosition,
+    Main_DirectDrawSurface_SetPalette,
+    Main_DirectDrawSurface_Unlock,
+    Main_DirectDrawSurface_UpdateOverlay,
+    Main_DirectDrawSurface_UpdateOverlayDisplay,
+    Main_DirectDrawSurface_UpdateOverlayZOrder,
+    Main_DirectDrawSurface_GetDDInterface,
+    Main_DirectDrawSurface_PageLock,
+    Main_DirectDrawSurface_PageUnlock,
+    FakeZBuffer_DirectDrawSurface_SetSurfaceDesc,
+    Main_DirectDrawSurface_SetPrivateData,
+    Main_DirectDrawSurface_GetPrivateData,
+    Main_DirectDrawSurface_FreePrivateData,
+    Main_DirectDrawSurface_GetUniquenessValue,
+    Main_DirectDrawSurface_ChangeUniquenessValue,
+    Main_DirectDrawSurface_SetPriority,
+    Main_DirectDrawSurface_GetPriority,
+    Main_DirectDrawSurface_SetLOD,
+    Main_DirectDrawSurface_GetLOD
+};
diff --git a/dlls/ddraw/dsurface/fakezbuffer.h b/dlls/ddraw/dsurface/fakezbuffer.h
new file mode 100644
index 0000000..9d419f4
--- /dev/null
+++ b/dlls/ddraw/dsurface/fakezbuffer.h
@@ -0,0 +1,33 @@
+/* Copyright 200 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_FAKEZBUFFER_H_INCLUDED
+#define DDRAW_DSURFACE_FAKEZBUFFER_H_INCLUDED
+
+struct FakeZBuffer_DirectDrawSurfaceImpl_Part
+{
+};
+
+typedef struct
+{
+    struct FakeZBuffer_DirectDrawSurfaceImpl_Part fakezbuffer;
+} FakeZBuffer_DirectDrawSurfaceImpl;
+
+HRESULT
+FakeZBuffer_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+					IDirectDrawImpl* pDD,
+					const DDSURFACEDESC2* pDDSD);
+
+HRESULT FakeZBuffer_DirectDrawSurface_Create(IDirectDrawImpl* pDD,
+					     const DDSURFACEDESC2* pDDSD,
+					     LPDIRECTDRAWSURFACE7* ppSurf,
+					     IUnknown* pUnkOuter);
+
+void
+FakeZBuffer_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This);
+
+HRESULT
+FakeZBuffer_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						LPDIRECTDRAWSURFACE7* ppDup);
+
+
+#endif
diff --git a/dlls/ddraw/dsurface/main.c b/dlls/ddraw/dsurface/main.c
index c6243a4..5ecad33 100644
--- a/dlls/ddraw/dsurface/main.c
+++ b/dlls/ddraw/dsurface/main.c
@@ -2,1180 +2,1075 @@
  *
  * Copyright 1997-2000 Marcus Meissner
  * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
+ * Copyright 2000 TransGaming Technologies Inc.
  */
 #include "config.h"
 #include "winerror.h"
 
-
-#include <unistd.h>
 #include <assert.h>
-#include <fcntl.h>
 #include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
 
 #include "debugtools.h"
-#include "bitmap.h"
 #include "ddraw_private.h"
+#include "dsurface/main.h"
+#include "ddraw/main.h"
+#include "dsurface/thunks.h"
 
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
-/******************************************************************************
- *		IDirectDrawSurface methods
- *
- * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
- * DDS and DDS2 use those functions. (Function calls did not change (except
- * using different DirectDrawSurfaceX version), just added flags and functions)
- */
+/** Creation/Destruction functions */
 
-HRESULT WINAPI IDirectDrawSurface4Impl_Lock(
-    LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
+HRESULT
+Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
+				 IDirectDrawImpl *pDD,
+				 const DDSURFACEDESC2 *pDDSD)
+{
+    if (pDDSD != &This->surface_desc)
+	This->surface_desc = *pDDSD;
+    This->uniqueness_value = 1; /* unchecked */
+    This->ref = 1;
 
-    TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
-	This,lprect,lpddsd,flags,(DWORD)hnd);
+    This->final_release = Main_DirectDrawSurface_final_release;
+    This->attach = Main_DirectDrawSurface_attach;
+    This->detach = Main_DirectDrawSurface_detach;
+    This->lock_update = Main_DirectDrawSurface_lock_update;
+    This->unlock_update = Main_DirectDrawSurface_unlock_update;
+    This->lose_surface = Main_DirectDrawSurface_lose_surface;
+    This->set_palette    = Main_DirectDrawSurface_set_palette;
+    This->update_palette = Main_DirectDrawSurface_update_palette;
+    This->get_display_window = Main_DirectDrawSurface_get_display_window;
 
-    /* DO NOT AddRef the surface! Lock/Unlock must not come in matched pairs
-     * -Marcus Meissner 20000509
-     */
-    if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
-	WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
-		 This,lprect,lpddsd,flags,(DWORD)hnd);
+    ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
+			DDRAW_IDDS3_Thunk_VTable);
+    /* There is no generic implementation of IDDS7 */
 
-    /* First, copy the Surface description */
-    *lpddsd = This->s.surface_desc;
-    TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
-	  lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
-
-    /* If asked only for a part, change the surface pointer */
-    if (lprect) {
-	TRACE("	lprect: %dx%d-%dx%d\n",
-		lprect->top,lprect->left,lprect->bottom,lprect->right
-	);
-	if ((lprect->top < 0) ||
-	    (lprect->left < 0) ||
-	    (lprect->bottom < 0) ||
-	    (lprect->right < 0)) {
-	  ERR(" Negative values in LPRECT !!!\n");
-	  return DDERR_INVALIDPARAMS;
-       }
-       
-	lpddsd->u1.lpSurface = (LPVOID) ((char *) This->s.surface_desc.u1.lpSurface +
-		(lprect->top*This->s.surface_desc.lPitch) +
-		lprect->left*GET_BPP(This->s.surface_desc));
-    } else {
-	assert(This->s.surface_desc.u1.lpSurface);
-    }
+    Main_DirectDraw_AddSurface(pDD, This);
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_Unlock(
-    LPDIRECTDRAWSURFACE4 iface,LPVOID surface
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
+void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
+{
+    Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
+}
 
-    /* DO NOT Release the surface! Lock/Unlock MUST NOT come in matched pairs
-     * Marcus Meissner 20000509
-     */
-    TRACE("(%p)->Unlock(%p)\n",This,surface);
+static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
+{
+    This->final_release(This);
+    if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
+    HeapFree(GetProcessHeap(), 0, This);
+}
+
+void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
+{
+    WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
+    Main_DirectDrawSurface_Destroy(This);
+}
+
+ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    if (--This->ref == 0)
+    {
+	if (This->aux_release)
+	    This->aux_release(This->aux_ctx, This->aux_data);
+	Main_DirectDrawSurface_Destroy(This);
+	return 0;
+    }
+
+    return This->ref;
+}
+
+ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    return ++This->ref;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
+				      LPVOID* ppObj)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
+
+    if (IsEqualGUID(&IID_IUnknown, riid)
+	|| IsEqualGUID(&IID_IDirectDrawSurface7, riid)
+	|| IsEqualGUID(&IID_IDirectDrawSurface4, riid))
+    {
+	This->ref++;
+	*ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
+	return S_OK;
+    }
+    else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
+	     || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
+	     || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
+    {
+	This->ref++;
+	*ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
+	return S_OK;
+    }
+    else
+	return E_NOINTERFACE;
+}
+
+/*** Callbacks */
+
+BOOL
+Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
+			      IDirectDrawSurfaceImpl *to)
+{
+    return TRUE;
+}
+
+BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
+{
+    return TRUE;
+}
+
+void
+Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
+{
+}
+
+void
+Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
+				     LPCRECT pRect)
+{
+}
+
+void
+Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
+{
+}
+
+void
+Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+				   IDirectDrawPaletteImpl* pal)
+{
+}
+
+void
+Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+				      IDirectDrawPaletteImpl* pal,
+				      DWORD dwStart, DWORD dwCount,
+				      LPPALETTEENTRY palent)
+{
+}
+
+HWND
+Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
+{
+    return 0;
+}
+
+
+/*** Interface functions */
+
+HRESULT WINAPI
+Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
+					  LPDIRECTDRAWSURFACE7 pAttach)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
+					       IDirectDrawSurface7, pAttach);
+
+    TRACE("(%p)->(%p)\n",This,pAttach);
+
+    /* Does windows check this? */
+    if (surf == This)
+	return DDERR_CANNOTATTACHSURFACE; /* unchecked */
+
+    /* Does windows check this? */
+    if (surf->ddraw_owner != This->ddraw_owner)
+	return DDERR_CANNOTATTACHSURFACE; /* unchecked */
+
+    if (surf->surface_owner != NULL)
+	return DDERR_SURFACEALREADYATTACHED; /* unchecked */
+
+    /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
+     * But apparently backbuffers and mipmaps can be attached too. */
+
+    /* Callback to allow the surface to do something special now that it is
+     * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
+    if (!surf->attach(surf, This))
+	return DDERR_CANNOTATTACHSURFACE;
+
+    /* check: Where should it go in the chain? This puts it on the head. */
+    if (This->attached)
+	This->attached->prev_attached = surf;
+    surf->next_attached = This->attached;
+    surf->prev_attached = NULL;
+    This->attached = surf;
+    surf->surface_owner = This;
+
+    IDirectDrawSurface7_AddRef(pAttach);
+
     return DD_OK;
 }
 
-IDirectDrawSurface4Impl* _common_find_flipto(
-    IDirectDrawSurface4Impl* This,IDirectDrawSurface4Impl* flipto
-) {
-    int	i,j,flipable=0;
-    struct _surface_chain	*chain = This->s.chain;
+/* MSDN: "not currently implemented." */
+HRESULT WINAPI
+Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
+					   LPRECT pRect)
+{
+    TRACE("(%p)->(%p)\n",iface,pRect);
+    return DDERR_UNSUPPORTED; /* unchecked */
+}
 
-    if (!chain) {
-	ERR("No flip chain? -> returning This.\n");
-	return This;
+/* MSDN: "not currently implemented." */
+HRESULT WINAPI
+Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
+				LPDDBLTBATCH pBatch, DWORD dwCount,
+				DWORD dwFlags)
+{
+    TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
+    return DDERR_UNSUPPORTED; /* unchecked */
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    volatile IDirectDrawSurfaceImpl* vThis = This;
+
+    TRACE("(%p)\n",This);
+    /* A uniquness value of 0 is apparently special.
+     * This needs to be checked. */
+    while (1)
+    {
+	DWORD old_uniqueness_value = vThis->uniqueness_value;
+	DWORD new_uniqueness_value = old_uniqueness_value+1;
+
+	if (old_uniqueness_value == 0) break;
+	if (new_uniqueness_value == 0) new_uniqueness_value = 1;
+
+	if (InterlockedCompareExchange(&vThis->uniqueness_value,
+				       old_uniqueness_value,
+				       new_uniqueness_value)
+	    == old_uniqueness_value)
+	    break;
     }
 
-    /* if there was no override flipto, look for current backbuffer */
-    if (!flipto) {
-	/* walk the flip chain looking for backbuffer */
-	for (i=0;i<chain->nrofsurfaces;i++) {
-	    if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP)
-	    	flipable++;
-	    if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_BACKBUFFER)
-		flipto = chain->surfaces[i];
-	}
-	/* sanity checks ... */
-	if (!flipto) {
-	    if (flipable>1) {
-		for (i=0;i<chain->nrofsurfaces;i++)
-		    if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FRONTBUFFER)
-		    	break;
-		if (i==chain->nrofsurfaces) {
-		    /* we do not have a frontbuffer either */
-		    for (i=0;i<chain->nrofsurfaces;i++)
-			if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP) {
-			    SDDSCAPS(chain->surfaces[i])|=DDSCAPS_FRONTBUFFER;
-			    break;
-			}
-		    for (j=i+1;j<i+chain->nrofsurfaces+1;j++) {
-		    	int k = j % chain->nrofsurfaces;
-			if (SDDSCAPS(chain->surfaces[k]) & DDSCAPS_FLIP) {
-			    SDDSCAPS(chain->surfaces[k])|=DDSCAPS_BACKBUFFER;
-			    flipto = chain->surfaces[k];
-			    break;
-			}
-		    }
-		}
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
+					     DWORD dwFlags,
+					     LPDIRECTDRAWSURFACE7 pAttach)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
+					       IDirectDrawSurface7, pAttach);
+
+    TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
+
+    if (!surf || (surf->surface_owner != This))
+	return DDERR_SURFACENOTATTACHED; /* unchecked */
+
+    surf->detach(surf);
+
+    if (surf->next_attached)
+	surf->next_attached->prev_attached = surf->prev_attached;
+    if (surf->prev_attached)
+	surf->prev_attached->next_attached = surf->next_attached;
+    if (This->attached == surf)
+	This->attached = surf->next_attached;
+
+    IDirectDrawSurface7_Release(pAttach);
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
+					    LPVOID context,
+					    LPDDENUMSURFACESCALLBACK7 cb)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    IDirectDrawSurfaceImpl* surf;
+
+    TRACE("(%p)->(%p,%p)\n",This,context,cb);
+
+    for (surf = This->attached; surf != NULL; surf = surf->next_attached)
+    {
+	/* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
+	if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
+	       context) == DDENUMRET_CANCEL)
+	    break;
+    }
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
+					  DWORD dwFlags, LPVOID context,
+					  LPDDENUMSURFACESCALLBACK7 cb)
+{
+    TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
+    return DD_OK;
+}
+
+void Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				      IDirectDrawSurfaceImpl* back)
+{
+    /* uniqueness_value? */
+    /* This is necessary. But is it safe? */
+    {
+	HDC tmp = front->hDC;
+	front->hDC = back->hDC;
+	back->hDC = tmp;
+    }
+
+    {
+	BOOL tmp = front->dc_in_use;
+	front->dc_in_use = back->dc_in_use;
+	back->dc_in_use = tmp;
+    }
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
+			    LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    IDirectDrawSurfaceImpl* target;
+    HRESULT hr;
+
+    TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
+
+    /* MSDN: "This method can be called only for a surface that has the
+     * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
+    if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
+	!= (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
+	return DDERR_NOTFLIPPABLE;
+
+    if (This->aux_flip)
+	if (This->aux_flip(This->aux_ctx, This->aux_data))
+	    return DD_OK;
+
+    /* 1. find the flip target */
+    /* XXX I don't think this algorithm works for more than 1 backbuffer. */
+    if (override == NULL)
+    {
+	static const DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
+	LPDIRECTDRAWSURFACE7 tgt;
+
+	hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
+	if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
+
+	target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
+			     tgt);
+	IDirectDrawSurface7_Release(tgt);
+    }
+    else
+    {
+	BOOL on_chain = FALSE;
+	IDirectDrawSurfaceImpl* surf;
+
+	/* MSDN: "The method fails if the specified [override] surface is not
+	 * a member of the flipping chain." */
+	
+	/* Verify that override is on this flip chain. We assume that
+	 * surf is the head of the flipping chain, because it's the front
+	 * buffer. */
+	target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
+			     override);
+
+	/* Either target is (indirectly) attached to This or This is
+	 * (indirectly) attached to target. */
+	for (surf = target; surf != NULL; surf = surf->surface_owner)
+	{
+	    if (surf == This)
+	    {
+		on_chain = TRUE;
+		break;
 	    }
-	    if (!flipto)
-		flipto = This;
-	}
-	TRACE("flipping to %p\n",flipto);
-    }
-    return flipto;
-}
-
-static HRESULT _Blt_ColorFill(
-    LPBYTE buf, int width, int height, int bpp, LONG lPitch, DWORD color
-) {
-    int x, y;
-    LPBYTE first;
-
-    /* Do first row */
-
-#define COLORFILL_ROW(type) { \
-    type *d = (type *) buf; \
-    for (x = 0; x < width; x++) \
-	d[x] = (type) color; \
-    break; \
-}
-
-    switch(bpp) {
-    case 1: COLORFILL_ROW(BYTE)
-    case 2: COLORFILL_ROW(WORD)
-    case 4: COLORFILL_ROW(DWORD)
-    default:
-	FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
-	return DDERR_UNSUPPORTED;
-    }
-
-#undef COLORFILL_ROW
-
-    /* Now copy first row */
-    first = buf;
-    for (y = 1; y < height; y++) {
-	buf += lPitch;
-	memcpy(buf, first, width * bpp);
-    }
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_Blt(
-    LPDIRECTDRAWSURFACE4 iface,LPRECT rdst,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,
-    DWORD dwFlags,LPDDBLTFX lpbltfx
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    RECT		xdst,xsrc;
-    DDSURFACEDESC	ddesc,sdesc;
-    HRESULT		ret = DD_OK;
-    int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
-    int x, y;
-    LPBYTE dbuf, sbuf;
-
-    TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
-
-    if (src) IDirectDrawSurface4_Lock(src, NULL, &sdesc, 0, 0);
-    IDirectDrawSurface4_Lock(iface,NULL,&ddesc,0,0);
-
-    if (TRACE_ON(ddraw)) {
-	if (rdst) TRACE("\tdestrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
-	if (rsrc) TRACE("\tsrcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
-	TRACE("\tflags: ");
-	_dump_DDBLT(dwFlags);
-	if (dwFlags & DDBLT_DDFX) {
-	    TRACE("\tblitfx: ");
-	    _dump_DDBLTFX(lpbltfx->dwDDFX);
-	}
-    }
-
-    if (rdst) {
-	if ((rdst->top < 0) ||
-	    (rdst->left < 0) ||
-	    (rdst->bottom < 0) ||
-	    (rdst->right < 0)) {
-	  ERR(" Negative values in LPRECT !!!\n");
-	  goto release;
-	}
-	memcpy(&xdst,rdst,sizeof(xdst));
-    } else {
-	xdst.top	= 0;
-	xdst.bottom	= ddesc.dwHeight;
-	xdst.left	= 0;
-	xdst.right	= ddesc.dwWidth;
-    }
-
-    if (rsrc) {
-	if ((rsrc->top < 0) ||
-	    (rsrc->left < 0) ||
-	    (rsrc->bottom < 0) ||
-	    (rsrc->right < 0)) {
-	  ERR(" Negative values in LPRECT !!!\n");
-	  goto release;
-	}
-	memcpy(&xsrc,rsrc,sizeof(xsrc));
-    } else {
-	if (src) {
-	    xsrc.top	= 0;
-	    xsrc.bottom	= sdesc.dwHeight;
-	    xsrc.left	= 0;
-	    xsrc.right	= sdesc.dwWidth;
-	} else {
-	    memset(&xsrc,0,sizeof(xsrc));
-	}
-    }
-    if (src) assert((xsrc.bottom-xsrc.top) <= sdesc.dwHeight);
-
-    /* truncate dst rect to dest surface. */
-    if ((xdst.bottom-xdst.top) > ddesc.dwHeight)
-	xdst.bottom = xdst.top+ddesc.dwHeight;
-    if ((xdst.right-xdst.left) > ddesc.dwWidth)
-	xdst.right = xdst.left+ddesc.dwWidth;
-
-    bpp = GET_BPP(ddesc);
-    srcheight = xsrc.bottom - xsrc.top;
-    srcwidth = xsrc.right - xsrc.left;
-    dstheight = xdst.bottom - xdst.top;
-    dstwidth = xdst.right - xdst.left;
-    width = (xdst.right - xdst.left) * bpp;
-
-    assert(width <= ddesc.lPitch);
-
-    dbuf = (BYTE*)ddesc.u1.lpSurface+(xdst.top*ddesc.lPitch)+(xdst.left*bpp);
-
-    dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
-
-    /* First, all the 'source-less' blits */
-    if (dwFlags & DDBLT_COLORFILL) {
-	ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
-			     ddesc.lPitch, lpbltfx->u4.dwFillColor);
-	dwFlags &= ~DDBLT_COLORFILL;
-    }
-
-    if (dwFlags & DDBLT_DEPTHFILL)
-	FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
-    if (dwFlags & DDBLT_ROP) {
-	/* Catch some degenerate cases here */
-	switch(lpbltfx->dwROP) {
-	case BLACKNESS:
-	    ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.lPitch,0);
-	    break;
-	case 0xAA0029: /* No-op */
-	    break;
-	case WHITENESS:
-	    ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.lPitch,~0);
-	    break;
-	case SRCCOPY: /* well, we do that below ? */
-	    break;
-	default: 
-	    FIXME("Unsupported raster op: %08lx  Pattern: %p\n", lpbltfx->dwROP, lpbltfx->u4.lpDDSPattern);
-	    goto error;
-	}
-	dwFlags &= ~DDBLT_ROP;
-    }
-    if (dwFlags & DDBLT_DDROPS) {
-	FIXME("\tDdraw Raster Ops: %08lx  Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u4.lpDDSPattern);
-    }
-    /* Now the 'with source' blits */
-    if (src) {
-	LPBYTE sbase;
-	int sx, xinc, sy, yinc;
-
-	if (!dstwidth || !dstheight) /* hmm... stupid program ? */
-	    goto release;
-	sbase = (BYTE*)sdesc.u1.lpSurface+(xsrc.top*sdesc.lPitch)+xsrc.left*bpp;
-	xinc = (srcwidth << 16) / dstwidth;
-	yinc = (srcheight << 16) / dstheight;
-
-	if (!dwFlags) {
-	    /* No effects, we can cheat here */
-	    if (dstwidth == srcwidth) {
-		if (dstheight == srcheight) {
-		    /* No stretching in either direction. This needs to be as
-		     * fast as possible */
-		    sbuf = sbase;
-		    for (y = 0; y < dstheight; y++) {
-			memcpy(dbuf, sbuf, width);
-			sbuf += sdesc.lPitch;
-			dbuf += ddesc.lPitch;
-		    }
-		} else {
-		    /* Stretching in Y direction only */
-		    for (y = sy = 0; y < dstheight; y++, sy += yinc) {
-			sbuf = sbase + (sy >> 16) * sdesc.lPitch;
-			memcpy(dbuf, sbuf, width);
-			dbuf += ddesc.lPitch;
-		    }
-		}
-	    } else {
-		/* Stretching in X direction */
-		int last_sy = -1;
-		for (y = sy = 0; y < dstheight; y++, sy += yinc) {
-		    sbuf = sbase + (sy >> 16) * sdesc.lPitch;
-
-		    if ((sy >> 16) == (last_sy >> 16)) {
-			/* this sourcerow is the same as last sourcerow -
-			 * copy already stretched row
-			 */
-			memcpy(dbuf, dbuf - ddesc.lPitch, width);
-		    } else {
-#define STRETCH_ROW(type) { \
-		    type *s = (type *) sbuf, *d = (type *) dbuf; \
-		    for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
-		    d[x] = s[sx >> 16]; \
-		    break; }
-
-		    switch(bpp) {
-		    case 1: STRETCH_ROW(BYTE)
-		    case 2: STRETCH_ROW(WORD)
-		    case 4: STRETCH_ROW(DWORD)
-		    case 3: {
-			LPBYTE s,d = dbuf;
-			for (x = sx = 0; x < dstwidth; x++, sx+= xinc) {
-			    DWORD pixel;
-
-			    s = sbuf+3*(sx>>16);
-			    pixel = (s[0]<<16)|(s[1]<<8)|s[2];
-			    d[0] = (pixel>>16)&0xff;
-			    d[1] = (pixel>> 8)&0xff;
-			    d[2] = (pixel    )&0xff;
-			    d+=3;
-			}
-			break;
-		    }
-		    default:
-			FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
-			ret = DDERR_UNSUPPORTED;
-			goto error;
-		    }
-#undef STRETCH_ROW
-		    }
-		    dbuf += ddesc.lPitch;
-		    last_sy = sy;
-		}
-	    }
-	} else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST)) {
-	    DWORD keylow, keyhigh;
-
-	    if (dwFlags & DDBLT_KEYSRC) {
-		keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
-		keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
-	    } else {
-		/* I'm not sure if this is correct */
-		FIXME("DDBLT_KEYDEST not fully supported yet.\n");
-		keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
-		keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
-	    }
-
-
-	    for (y = sy = 0; y < dstheight; y++, sy += yinc) {
-		sbuf = sbase + (sy >> 16) * sdesc.lPitch;
-
-#define COPYROW_COLORKEY(type) { \
-		type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
-		for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
-		    tmp = s[sx >> 16]; \
-		    if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
-		} \
-		break; }
-
-		switch (bpp) {
-		case 1: COPYROW_COLORKEY(BYTE)
-		case 2: COPYROW_COLORKEY(WORD)
-		case 4: COPYROW_COLORKEY(DWORD)
-		default:
-		    FIXME("%s color-keyed blit not implemented for bpp %d!\n",
-		    (dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
-		    ret = DDERR_UNSUPPORTED;
-		    goto error;
-		}
-		dbuf += ddesc.lPitch;
-	    }
-#undef COPYROW_COLORKEY
-	    dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST);
-	}
-    }
-
-error:
-    if (dwFlags && FIXME_ON(ddraw)) {
-	FIXME("\tUnsupported flags: ");
-	_dump_DDBLT(dwFlags);
-    }
-
-release:
-    IDirectDrawSurface4_Unlock(iface,ddesc.u1.lpSurface);
-    if (src) IDirectDrawSurface4_Unlock(src,sdesc.u1.lpSurface);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_BltFast(
-    LPDIRECTDRAWSURFACE4 iface,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE4 src,
-    LPRECT rsrc,DWORD trans
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    int			bpp, w, h, x, y;
-    DDSURFACEDESC	ddesc,sdesc;
-    HRESULT		ret = DD_OK;
-    LPBYTE		sbuf, dbuf;
-    RECT		rsrc2;
-
-
-    if (TRACE_ON(ddraw)) {
-	FIXME("(%p)->(%ld,%ld,%p,%p,%08lx)\n",
-		This,dstx,dsty,src,rsrc,trans
-	);
-	FIXME("	trans:");
-	if (FIXME_ON(ddraw))
-	  _dump_DDBLTFAST(trans);
-	if (rsrc)
-	  FIXME("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
-	else
-	  FIXME(" srcrect: NULL\n");
-    }
-    
-    /* We need to lock the surfaces, or we won't get refreshes when done. */
-    IDirectDrawSurface4_Lock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
-    IDirectDrawSurface4_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
-
-   if (!rsrc) {
-	   WARN("rsrc is NULL!\n");
-	   rsrc = &rsrc2;
-	   rsrc->left = rsrc->top = 0;
-	   rsrc->right = sdesc.dwWidth;
-	   rsrc->bottom = sdesc.dwHeight;
-   }
-
-    bpp = GET_BPP(This->s.surface_desc);
-    sbuf = (BYTE *)sdesc.u1.lpSurface+(rsrc->top*sdesc.lPitch)+rsrc->left*bpp;
-    dbuf = (BYTE *)ddesc.u1.lpSurface+(dsty*ddesc.lPitch)+dstx* bpp;
-
-
-    h=rsrc->bottom-rsrc->top;
-    if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
-    if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
-    if (h<0) h=0;
-
-    w=rsrc->right-rsrc->left;
-    if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
-    if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
-    if (w<0) w=0;
-
-    if (trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) {
-	DWORD keylow, keyhigh;
-	if (trans & DDBLTFAST_SRCCOLORKEY) {
-	    keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
-	    keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
-	} else {
-	    /* I'm not sure if this is correct */
-	    FIXME("DDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
-	    keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
-	    keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
 	}
 
-#define COPYBOX_COLORKEY(type) { \
-    type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
-    s = (type *) ((BYTE *) sdesc.u1.lpSurface + (rsrc->top * sdesc.lPitch) + rsrc->left * bpp); \
-    d = (type *) ((BYTE *) ddesc.u1.lpSurface + (dsty * ddesc.lPitch) + dstx * bpp); \
-    for (y = 0; y < h; y++) { \
-	for (x = 0; x < w; x++) { \
-	    tmp = s[x]; \
-	    if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
-	} \
-	(LPBYTE)s += sdesc.lPitch; \
-	(LPBYTE)d += ddesc.lPitch; \
-    } \
-    break; \
-}
-
-	switch (bpp) {
-	case 1: COPYBOX_COLORKEY(BYTE)
-	case 2: COPYBOX_COLORKEY(WORD)
-	case 4: COPYBOX_COLORKEY(DWORD)
-	default:
-	    FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
-	    ret = DDERR_UNSUPPORTED;
-	    goto error;
-	}
-#undef COPYBOX_COLORKEY
-    } else {
-	int width = w * bpp;
-
-	for (y = 0; y < h; y++) {
-	    memcpy(dbuf, sbuf, width);
-	    sbuf += sdesc.lPitch;
-	    dbuf += ddesc.lPitch;
-	}
+	if (!on_chain)
+	    return DDERR_INVALIDPARAMS; /* unchecked */
     }
-error:
-    IDirectDrawSurface4_Unlock(iface,ddesc.u1.lpSurface);
-    IDirectDrawSurface4_Unlock(src,sdesc.u1.lpSurface);
-    return ret;
-}
 
-HRESULT WINAPI IDirectDrawSurface4Impl_BltBatch(
-    LPDIRECTDRAWSURFACE4 iface,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",This,ddbltbatch,x,y);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetCaps(
-    LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS caps
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->GetCaps(%p)\n",This,caps);
-    caps->dwCaps = DDSCAPS_PALETTE; /* probably more */
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetSurfaceDesc(
-    LPDIRECTDRAWSURFACE4 iface,LPDDSURFACEDESC ddsd
-) { 
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->GetSurfaceDesc(%p)\n", This,ddsd);
-  
-    /* Simply copy the surface description stored in the object */
-    *ddsd = This->s.surface_desc;
-  
-    if (TRACE_ON(ddraw)) { _dump_surface_desc(ddsd); }
+    TRACE("flip to backbuffer: %p\n",target);
+    This->flip_data(This, target);
+    This->flip_update(This);
 
     return DD_OK;
 }
 
-ULONG WINAPI IDirectDrawSurface4Impl_AddRef(LPDIRECTDRAWSURFACE4 iface) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
-    return ++(This->ref);
+static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
+				      REFGUID tag)
+{
+    PrivateData* data;
+    for (data = This->private_data; data != NULL; data = data->next)
+    {
+	if (IsEqualGUID(&data->tag, tag)) break;
+    }
+
+    return data;
 }
 
+HRESULT WINAPI
+Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    PrivateData *data;
 
-HRESULT WINAPI IDirectDrawSurface4Impl_GetAttachedSurface(
-    LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE4 *lpdsf
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    int	i,found = 0,xstart;
-    struct _surface_chain	*chain;
+    data = find_private_data(This, tag);
+    if (data == NULL) return DDERR_NOTFOUND;
 
-    TRACE("(%p)->GetAttachedSurface(%p,%p)\n", This, lpddsd, lpdsf);
-    if (TRACE_ON(ddraw)) {
-	TRACE("	caps ");_dump_DDSCAPS((void *) &(lpddsd->dwCaps));
-	DPRINTF("\n");
+    if (data->prev)
+	data->prev->next = data->next;
+    if (data->next)
+	data->next->prev = data->prev;
+
+    if (data->flags & DDSPD_IUNKNOWNPTR)
+    {
+	if (data->ptr.object != NULL)
+	    IUnknown_Release(data->ptr.object);
     }
-    chain = This->s.chain;
-    if (!chain)
-    	return DDERR_NOTFOUND;
+    else
+	HeapFree(GetProcessHeap(), 0, data->ptr.data);
 
-    for (i=0;i<chain->nrofsurfaces;i++)
-    	if (chain->surfaces[i] == This)
-	    break;
+    HeapFree(GetProcessHeap(), 0, data);
 
-    xstart = i;
-    for (i=0;i<chain->nrofsurfaces;i++) {
-	if ((SDDSCAPS(chain->surfaces[(xstart+i)%chain->nrofsurfaces])&lpddsd->dwCaps) == lpddsd->dwCaps) {
-#if 0
-	    if (found) /* may not find the same caps twice, (doc) */
-		return DDERR_INVALIDPARAMS;/*FIXME: correct? */
-#endif
-	    found = (i+1)+xstart;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
+					  LPDDSCAPS2 pCaps,
+					  LPDIRECTDRAWSURFACE7* ppSurface)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    IDirectDrawSurfaceImpl* surf;
+    IDirectDrawSurfaceImpl* found = NULL;
+
+    TRACE("(%p)->Looking for caps: %x,%x,%x,%x output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2, 
+          pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
+
+    for (surf = This->attached; surf != NULL; surf = surf->next_attached)
+    {
+        TRACE("Surface: (%p) caps: %x,%x,%x,%x \n",surf ,
+               surf->surface_desc.ddsCaps.dwCaps,
+               surf->surface_desc.ddsCaps.dwCaps2,
+               surf->surface_desc.ddsCaps.dwCaps3,
+               surf->surface_desc.ddsCaps.dwCaps4);
+	if (((surf->surface_desc.ddsCaps.dwCaps & pCaps->dwCaps) == pCaps->dwCaps)
+	   && ((surf->surface_desc.ddsCaps.dwCaps2 & pCaps->dwCaps2) == pCaps->dwCaps2))
+	{
+	    /* MSDN: "This method fails if more than one surface is attached
+	     * that matches the capabilities requested." */
+	    if (found != NULL)
+            {
+                FIXME("More than one attached surface matches requested caps.  What should we do here?\n");
+                /* Previous code returned 'DDERR_NOTFOUND'.  That appears not 
+                   to be correct, given what 3DMark expects from MipMapped surfaces. 
+                   We shall just continue instead. */
+            }
+
+	    found = surf;
 	}
     }
-    if (!found)
+
+    if (found == NULL)
 	return DDERR_NOTFOUND;
-    *lpdsf = (LPDIRECTDRAWSURFACE4)chain->surfaces[found-1-xstart];
 
-    /* For EverQuest testing */
-    IDirectDrawSurface4_AddRef(*lpdsf);
-    
-    TRACE("found %p\n",*lpdsf);
+    *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
+
+    /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
+    IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_Initialize(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->(%p, %p)\n",This,ddraw,lpdsfd);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
+{
+    TRACE("(%p)->(%08lx)\n",iface,dwFlags);
 
+    switch (dwFlags)
+    {
+    case DDGBS_CANBLT:
+    case DDGBS_ISBLTDONE:
+	return DD_OK;
+
+    default:
+	return DDERR_INVALIDPARAMS;
+    }
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pCaps);
+    *pCaps = This->surface_desc.ddsCaps;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAWCLIPPER* ppClipper)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,ppClipper);
+    if (This->clipper == NULL)
+	return DDERR_NOCLIPPERATTACHED;
+
+    *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
+    IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
+					     IDirectDrawClipper));
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
+				   LPDDCOLORKEY pCKey)
+{
+    /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
+     * isn't there? That's like saying that an int isn't there. (Which MS
+     * has done in other docs.) */
+
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
+    switch (dwFlags)
+    {
+    case DDCKEY_DESTBLT:
+	*pCKey = This->surface_desc.ddckCKDestBlt;
+	break;
+
+    case DDCKEY_DESTOVERLAY:
+	*pCKey = This->surface_desc.u3.ddckCKDestOverlay;
+	break;
+
+    case DDCKEY_SRCBLT:
+	*pCKey = This->surface_desc.ddckCKSrcBlt;
+	break;
+
+    case DDCKEY_SRCOVERLAY:
+	*pCKey = This->surface_desc.ddckCKSrcOverlay;
+	break;
+
+    default:
+	return DDERR_INVALIDPARAMS;
+    }
+
+    return DD_OK;
+}
+
+/* XXX We need to do something with the DC if the surface gets lost. */
+HRESULT WINAPI
+Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
+{
+    DDSURFACEDESC2 ddsd;
+    HRESULT hr;
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,phDC);
+    CHECK_LOST(This);
+
+    LOCK_OBJECT(This);
+
+    if (This->dc_in_use)
+    {
+	UNLOCK_OBJECT(This);
+	return DDERR_DCALREADYCREATED;
+    }
+
+    /* Lock as per MSDN.
+     * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
+     * thread has it locked, but GetDC does not. */
+    ddsd.dwSize = sizeof(ddsd);
+    hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
+    if (FAILED(hr))
+    {
+	UNLOCK_OBJECT(This);
+	return hr;
+    }
+
+    hr = This->get_dc(This, &This->hDC);
+    if (SUCCEEDED(hr))
+    {
+	TRACE("returning %08x\n",This->hDC);
+
+	*phDC = This->hDC;
+	This->dc_in_use = TRUE;
+    }
+    else WARN("No DC! Prepare for trouble\n");
+
+    UNLOCK_OBJECT(This);
+    return hr;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pDD);
+    *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
+    IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
+{
+    /* XXX: DDERR_INVALIDSURFACETYPE */
+
+    TRACE("(%p)->(%08lx)\n",iface,dwFlags);
+    switch (dwFlags)
+    {
+    case DDGFS_CANFLIP:
+    case DDGFS_ISFLIPDONE:
+	return DD_OK;
+
+    default:
+	return DDERR_INVALIDPARAMS;
+    }
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
+    CHECK_TEXTURE(This);
+
+    *pdwMaxLOD = This->max_lod;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
+					  LPLONG pX, LPLONG pY)
+{
+    return DDERR_NOTAOVERLAYSURFACE;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAWPALETTE* ppPalette)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,ppPalette);
+    if (This->palette == NULL)
+	return DDERR_NOPALETTEATTACHED;
+
+    *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
+    IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
+					     IDirectDrawPalette));
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
+				      LPDDPIXELFORMAT pDDPixelFormat)
+{
+    /* What is DDERR_INVALIDSURFACETYPE for here? */
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
+    *pDDPixelFormat = This->surface_desc.u4.ddpfPixelFormat;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
+				   LPDWORD pdwPriority)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pdwPriority);
+    CHECK_TEXTURE(This);
+
+    *pdwPriority = This->priority;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
+				      REFGUID tag, LPVOID pBuffer,
+				      LPDWORD pcbBufferSize)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+    PrivateData* data;
+
+    data = find_private_data(This, tag);
+    if (data == NULL) return DDERR_NOTFOUND;
+
+    /* This may not be right. */
+    if ((data->flags & DDSPD_VOLATILE)
+	&& data->uniqueness_value != This->uniqueness_value)
+	return DDERR_EXPIRED;
+
+    if (*pcbBufferSize < data->size)
+    {
+	*pcbBufferSize = data->size;
+	return DDERR_MOREDATA;
+    }
+
+    if (data->flags & DDSPD_IUNKNOWNPTR)
+    {
+	*(LPUNKNOWN *)pBuffer = data->ptr.object;
+	IUnknown_AddRef(data->ptr.object);
+    }
+    else
+    {
+	memcpy(pBuffer, data->ptr.data, data->size);
+    }
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
+				      LPDDSURFACEDESC2 pDDSD)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pDDSD);
+    *pDDSD = This->surface_desc;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
+					  LPDWORD pValue)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pValue);
+    *pValue = This->uniqueness_value;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
+{
+    TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
     return DDERR_ALREADYINITIALIZED;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_GetPixelFormat(
-    LPDIRECTDRAWSURFACE4 iface,LPDDPIXELFORMAT pf
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->(%p)\n",This,pf);
-
-    *pf = This->s.surface_desc.ddpfPixelFormat;
-    if (TRACE_ON(ddraw)) { _dump_pixelformat(pf); DPRINTF("\n"); }
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetBltStatus(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(0x%08lx),stub!\n",This,dwFlags);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetOverlayPosition(
-    LPDIRECTDRAWSURFACE4 iface,LPLONG x1,LPLONG x2
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%p,%p),stub!\n",This,x1,x2);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_SetClipper(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWCLIPPER lpClipper
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->(%p)!\n",This,lpClipper);
-
-    if (This->s.lpClipper) IDirectDrawClipper_Release( This->s.lpClipper );
-    This->s.lpClipper = lpClipper;
-    if (lpClipper) IDirectDrawClipper_AddRef( lpClipper );
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_AddAttachedSurface(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 surf
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    IDirectDrawSurface4Impl*isurf = (IDirectDrawSurface4Impl*)surf;
-    int i;
-    struct _surface_chain *chain;
-
-    FIXME("(%p)->(%p)\n",This,surf);
-    chain = This->s.chain;
-
-    /* IDirectDrawSurface4_AddRef(surf); */
-    
-    if (chain) {
-	for (i=0;i<chain->nrofsurfaces;i++)
-	    if (chain->surfaces[i] == isurf)
-		FIXME("attaching already attached surface %p to %p!\n",iface,isurf);
-    } else {
-    	chain = HeapAlloc(GetProcessHeap(),0,sizeof(*chain));
-	chain->nrofsurfaces = 1;
-	chain->surfaces = HeapAlloc(GetProcessHeap(),0,sizeof(chain->surfaces[0]));
-	chain->surfaces[0] = This;
-	This->s.chain = chain;
-    }
-
-    if (chain->surfaces)
-	chain->surfaces = HeapReAlloc(
-	    GetProcessHeap(),
-	    0,
-	    chain->surfaces,
-	    sizeof(chain->surfaces[0])*(chain->nrofsurfaces+1)
-	);
-    else
-	chain->surfaces = HeapAlloc(GetProcessHeap(),0,sizeof(chain->surfaces[0]));
-    isurf->s.chain = chain;
-    chain->surfaces[chain->nrofsurfaces++] = isurf;
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DDSURFACEDESC desc;
-    BITMAPINFO *b_info;
-    UINT usage;
-    HDC ddc;
-
-    TRACE("(%p)->GetDC(%p)\n",This,lphdc);
-
-    /* Creates a DIB Section of the same size / format as the surface */
-    IDirectDrawSurface4_Lock(iface,NULL,&desc,0,0);
-
-    if (This->s.hdc == 0) {
-	switch (desc.ddpfPixelFormat.u.dwRGBBitCount) {
-	case 16:
-	case 32:
-#if 0 /* This should be filled if Wine's DIBSection did understand BI_BITFIELDS */
-	    b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
-	    break;
-#endif
-
-	case 24:
-	    b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
-	    break;
-
-	default:
-	    b_info = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-		    sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (2 << desc.ddpfPixelFormat.u.dwRGBBitCount));
-	    break;
-	}
-
-	b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-	b_info->bmiHeader.biWidth = desc.dwWidth;
-	b_info->bmiHeader.biHeight = -desc.dwHeight;
-	b_info->bmiHeader.biPlanes = 1;
-	b_info->bmiHeader.biBitCount = desc.ddpfPixelFormat.u.dwRGBBitCount;
-#if 0
-	if ((desc.ddpfPixelFormat.u.dwRGBBitCount != 16) &&
-	    (desc.ddpfPixelFormat.u.dwRGBBitCount != 32))
-#endif
-	b_info->bmiHeader.biCompression = BI_RGB;
-#if 0
-	else
-	b_info->bmiHeader.biCompression = BI_BITFIELDS;
-#endif
-	b_info->bmiHeader.biSizeImage = (desc.ddpfPixelFormat.u.dwRGBBitCount / 8) * desc.dwWidth * desc.dwHeight;
-	b_info->bmiHeader.biXPelsPerMeter = 0;
-	b_info->bmiHeader.biYPelsPerMeter = 0;
-	b_info->bmiHeader.biClrUsed = 0;
-	b_info->bmiHeader.biClrImportant = 0;
-
-	switch (desc.ddpfPixelFormat.u.dwRGBBitCount) {
-	case 16:
-	case 32:
-#if 0
-	    {
-		DWORD *masks = (DWORD *) &(b_info->bmiColors);
-
-		usage = 0;
-		masks[0] = desc.ddpfPixelFormat.u1.dwRBitMask;
-		masks[1] = desc.ddpfPixelFormat.u2.dwGBitMask;
-		masks[2] = desc.ddpfPixelFormat.u3.dwBBitMask;
-	    }
-	    break;
-#endif
-	case 24:
-	    /* Nothing to do */
-	    usage = DIB_RGB_COLORS;
-	    break;
-
-	default: {
-		int i;
-
-		/* Fill the palette */
-		usage = DIB_RGB_COLORS;
-
-		if (This->s.palette == NULL) {
-		    ERR("Bad palette !!!\n");
-		} else {
-		    RGBQUAD *rgb = (RGBQUAD *) &(b_info->bmiColors);
-		    PALETTEENTRY *pent = (PALETTEENTRY *)&(This->s.palette->palents);
-
-		    for (i=0;i<(1<<desc.ddpfPixelFormat.u.dwRGBBitCount);i++) {
-			rgb[i].rgbBlue = pent[i].peBlue;
-			rgb[i].rgbRed = pent[i].peRed;
-			rgb[i].rgbGreen = pent[i].peGreen; 
-		    }
-		}
-	    }
-	    break;
-	}
-	ddc = CreateDCA("DISPLAY",NULL,NULL,NULL);
-	This->s.DIBsection = ddc ? DIB_CreateDIBSection(ddc,
-	    b_info,
-	    usage,
-	    &(This->s.bitmap_data),
-	    0,
-	    (DWORD)desc.u1.lpSurface,
-	    desc.lPitch
-	) : 0;
-	if (!This->s.DIBsection) {
-		ERR("CreateDIBSection failed!\n");
-		if (ddc) DeleteDC(ddc);
-		HeapFree(GetProcessHeap(), 0, b_info);
-		return E_FAIL;
-	}
-	TRACE("DIBSection at : %p\n", This->s.bitmap_data);
-
-	/* b_info is not useful anymore */
-	HeapFree(GetProcessHeap(), 0, b_info);
-
-	/* Create the DC */
-	This->s.hdc = CreateCompatibleDC(ddc);
-	This->s.holdbitmap = SelectObject(This->s.hdc, This->s.DIBsection);
-
-	if (ddc) DeleteDC(ddc);
-    }
-
-    if (This->s.bitmap_data != desc.u1.lpSurface) {
-        FIXME("DIBSection not created for frame buffer, reverting to old code\n");
-	/* Copy our surface in the DIB section */
-	if ((GET_BPP(desc) * desc.dwWidth) == desc.lPitch)
-	    memcpy(This->s.bitmap_data,desc.u1.lpSurface,desc.lPitch*desc.dwHeight);
-	else
-	    /* TODO */
-	    FIXME("This case has to be done :/\n");
-    }
-
-    if (lphdc) {
-	TRACE("HDC : %08lx\n", (DWORD) This->s.hdc);
-	*lphdc = This->s.hdc;
-    }
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_ReleaseDC(LPDIRECTDRAWSURFACE4 iface,HDC hdc) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-
-    TRACE("(%p)->(0x%08lx)\n",This,(long)hdc);
-
-    if (This->s.bitmap_data != This->s.surface_desc.u1.lpSurface) {
-	TRACE( "Copying DIBSection at : %p\n", This->s.bitmap_data);
-	/* Copy the DIB section to our surface */
-	if ((GET_BPP(This->s.surface_desc) * This->s.surface_desc.dwWidth) == This->s.surface_desc.lPitch) {
-	    memcpy(This->s.surface_desc.u1.lpSurface, This->s.bitmap_data, This->s.surface_desc.lPitch * This->s.surface_desc.dwHeight);
-	} else {
-	    /* TODO */
-	    FIXME("This case has to be done :/\n");
-	}
-    }
-    /* Unlock the surface */
-    IDirectDrawSurface4_Unlock(iface,This->s.surface_desc.u1.lpSurface);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_QueryInterface(
-    LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-
-    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
-    
-    /* All DirectDrawSurface versions (1, 2, 3 and 4) use
-     * the same interface. And IUnknown does that too of course.
-     */
-    if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid )	||
-	 IsEqualGUID( &IID_IDirectDrawSurface3, refiid )	||
-	 IsEqualGUID( &IID_IDirectDrawSurface2, refiid )	||
-	 IsEqualGUID( &IID_IDirectDrawSurface,  refiid )	||
-	 IsEqualGUID( &IID_IUnknown,            refiid )
-    ) {
-	    *obj = This;
-	    IDirectDrawSurface4_AddRef(iface);
-
-	    TRACE("  Creating IDirectDrawSurface interface (%p)\n", *obj);
-	    return S_OK;
-    }
-    FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
-    return OLE_E_ENUM_NOMORE;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_IsLost(LPDIRECTDRAWSURFACE4 iface) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->(), stub!\n",This);
-    return DD_OK; /* hmm */
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_EnumAttachedSurfaces(
-    LPDIRECTDRAWSURFACE4 iface,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    int i;
-    struct _surface_chain *chain = This->s.chain;
-
-    TRACE("(%p)->(%p,%p)\n",This,context,esfcb);
-    if (chain) {
-	for (i=0;i<chain->nrofsurfaces;i++) {
-	    TRACE( "Enumerating attached surface (%p)\n", chain->surfaces[i]);
-	    if (esfcb((LPDIRECTDRAWSURFACE) chain->surfaces[i], &(chain->surfaces[i]->s.surface_desc), context) == DDENUMRET_CANCEL)
-		return DD_OK; /* FIXME: return value correct? */
-	}
-    }
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_Restore(LPDIRECTDRAWSURFACE4 iface) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(),stub!\n",This);
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_SetColorKey(
-    LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY ckey ) 
+HRESULT WINAPI
+Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
 {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->(0x%08lx,%p)\n",This,dwFlags,ckey);
-    if (TRACE_ON(ddraw)) {
-	_dump_colorkeyflag(dwFlags);
-	DPRINTF(" : ");
-	_dump_DDCOLORKEY((void *) ckey);
-	DPRINTF("\n");
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
+    return This->lost ? DDERR_SURFACELOST : DD_OK;
+}
+
+
+/* XXX This doesn't actually do any locking or keep track of the locked
+ * rectangles. The behaviour is poorly documented. */
+HRESULT WINAPI
+Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
+			    LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
+
+    if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
+	WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
+		 This,prect,pDDSD,flags,(DWORD)h);
+
+    /* First, copy the Surface description */
+    memcpy(pDDSD, &(This->surface_desc), pDDSD->dwSize);
+    TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
+	  pDDSD->dwHeight,pDDSD->dwWidth,pDDSD->u1.lPitch);
+
+    /* If asked only for a part, change the surface pointer.
+     * (Not documented.) */
+    if (prect != NULL) {
+	TRACE("	lprect: %dx%d-%dx%d\n",
+		prect->top,prect->left,prect->bottom,prect->right
+	);
+	if ((prect->top < 0) ||
+	    (prect->left < 0) ||
+	    (prect->bottom < 0) ||
+	    (prect->right < 0)) {
+	  ERR(" Negative values in LPRECT !!!\n");
+	  return DDERR_INVALIDPARAMS;
+       }
+
+	This->lock_update(This, prect);
+       
+	pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
+	    + prect->top * This->surface_desc.u1.lPitch
+	    + prect->left * GET_BPP(This->surface_desc);
     }
 
-    /* If this surface was loaded as a texture, call also the texture
-     * SetColorKey callback. FIXME: hack approach :(
-     */
-    if (This->s.texture)
-	This->s.SetColorKey_cb(This->s.texture, dwFlags, ckey);
-
-    if( dwFlags & DDCKEY_SRCBLT ) {
-	dwFlags &= ~DDCKEY_SRCBLT;
-	This->s.surface_desc.dwFlags |= DDSD_CKSRCBLT;
-	memcpy( &(This->s.surface_desc.ddckCKSrcBlt), ckey, sizeof( *ckey ) );
-    }
-
-    if( dwFlags & DDCKEY_DESTBLT ) {
-	dwFlags &= ~DDCKEY_DESTBLT;
-	This->s.surface_desc.dwFlags |= DDSD_CKDESTBLT;
-	memcpy( &(This->s.surface_desc.ddckCKDestBlt), ckey, sizeof( *ckey ) );
-    }
-
-    if( dwFlags & DDCKEY_SRCOVERLAY ) {
-	dwFlags &= ~DDCKEY_SRCOVERLAY;
-	This->s.surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
-	memcpy( &(This->s.surface_desc.ddckCKSrcOverlay), ckey, sizeof( *ckey ) );	   
-    }
-
-    if( dwFlags & DDCKEY_DESTOVERLAY ) {
-	dwFlags &= ~DDCKEY_DESTOVERLAY;
-	This->s.surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
-	memcpy( &(This->s.surface_desc.ddckCKDestOverlay), ckey, sizeof( *ckey ) );	   
-    }
-    if( dwFlags )
-	FIXME("unhandled dwFlags: 0x%08lx\n", dwFlags );
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_AddOverlayDirtyRect(
-    LPDIRECTDRAWSURFACE4 iface, LPRECT lpRect
-) {
-  ICOM_THIS(IDirectDrawSurface4Impl,iface);
-  FIXME("(%p)->(%p),stub!\n",This,lpRect); 
-
-  return DD_OK;
+HRESULT WINAPI
+Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
+{
+    /* Some surface types should return DDERR_CANTPAGELOCK. */
+    return DD_OK;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_DeleteAttachedSurface(
-    LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags,
-    LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    int i;
-    struct _surface_chain *chain;
+HRESULT WINAPI
+Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
+{
+    /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
+     * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
+    return DD_OK;
+}
 
-    TRACE("(%p)->(0x%08lx,%p)\n",This,dwFlags,lpDDSAttachedSurface);
-    chain = This->s.chain;
-    for (i=0;i<chain->nrofsurfaces;i++) {
-	if ((IDirectDrawSurface4Impl*)lpDDSAttachedSurface==chain->surfaces[i]){
-	    /* There is no AddRef in AddAttachedSurface, so why a release here :-) 
-	       IDirectDrawSurface4_Release(lpDDSAttachedSurface); */
+HRESULT WINAPI
+Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
+{
+    HRESULT hr;
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
 
-	    chain->surfaces[i]->s.chain = NULL;
-	    memcpy( chain->surfaces+i,
-		    chain->surfaces+(i+1),
-		    (chain->nrofsurfaces-i-1)*sizeof(chain->surfaces[i])
-	    );
-	    chain->surfaces = HeapReAlloc(
-		GetProcessHeap(),
-		0,
-		chain->surfaces,
-		sizeof(chain->surfaces[i])*(chain->nrofsurfaces-1)
-	    );
-	    chain->nrofsurfaces--;
-	    return DD_OK;
+    TRACE("(%p)->(%08x)\n",This,hDC);
+
+    if (!This->dc_in_use || This->hDC != hDC)
+	return DDERR_INVALIDPARAMS;
+
+    This->release_dc(This, hDC);
+
+    hr = IDirectDrawSurface7_Unlock(iface, NULL);
+    if (FAILED(hr)) return hr;
+
+    This->dc_in_use = FALSE;
+    This->hDC = 0;
+
+    return DD_OK;
+}
+
+/* Restore */
+
+HRESULT WINAPI
+Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAWCLIPPER pDDClipper)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pDDClipper);
+    if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
+	return DD_OK;
+
+    if (This->clipper != NULL)
+	IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
+						  IDirectDrawClipper));
+
+    This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
+				pDDClipper);
+    if (pDDClipper != NULL)
+	IDirectDrawClipper_AddRef(pDDClipper);
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
+				   DWORD dwFlags, LPDDCOLORKEY pCKey)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
+    if (pCKey == NULL)
+    {
+	FIXME("supposedly removing color key %lu\n",
+	      dwFlags & ~DDCKEY_COLORSPACE);
+	return DD_OK;
+    }
+
+    switch (dwFlags & ~DDCKEY_COLORSPACE)
+    {
+    case DDCKEY_DESTBLT:
+	This->surface_desc.ddckCKDestBlt = *pCKey;
+	break;
+
+    case DDCKEY_DESTOVERLAY:
+	This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
+	break;
+
+    case DDCKEY_SRCOVERLAY:
+	This->surface_desc.ddckCKSrcOverlay = *pCKey;
+	break;
+
+    case DDCKEY_SRCBLT:
+	This->surface_desc.ddckCKSrcBlt = *pCKey;
+	break;
+
+    default:
+	return DDERR_INVALIDPARAMS;
+    }
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
+    CHECK_TEXTURE(This);
+
+    This->max_lod = dwMaxLOD;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
+					  LONG X, LONG Y)
+{
+    return DDERR_NOTAOVERLAYSURFACE;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAWPALETTE pPalette)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%p)\n",This,pPalette);
+    if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
+	return DD_OK;
+
+    if (This->palette != NULL) {
+	if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+	    This->palette->flags &= ~DDPCAPS_PRIMARYSURFACE;
+	IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette,
+						  IDirectDrawPalette));
+    }
+
+    This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
+				pPalette);
+    if (pPalette != NULL) {
+	IDirectDrawPalette_AddRef(pPalette);
+	if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+	    This->palette->flags |= DDPCAPS_PRIMARYSURFACE;
+    }
+
+    This->set_palette(This, This->palette);
+
+    return DD_OK;
+}
+
+HRESULT WINAPI
+Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
+				   DWORD dwPriority)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    TRACE("(%p)->(%08lx)\n",This,dwPriority);
+    CHECK_TEXTURE(This);
+
+    This->priority = dwPriority;
+    return DD_OK;
+}
+
+/* Be careful when locking this: it is risky to call the object's AddRef
+ * or Release holding a lock. */
+HRESULT WINAPI
+Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
+				      REFGUID tag, LPVOID pData,
+				      DWORD cbSize, DWORD dwFlags)
+{
+    PrivateData* data;
+    ICOM_THIS(IDirectDrawSurfaceImpl, iface);
+
+    data = find_private_data(This, tag);
+    if (data == NULL)
+    {
+	data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
+	if (data == NULL) return DDERR_OUTOFMEMORY;
+
+	data->tag = *tag;
+	data->flags = dwFlags;
+	data->uniqueness_value = This->uniqueness_value;
+
+	if (dwFlags & DDSPD_IUNKNOWNPTR)
+	{
+	    data->ptr.object = (LPUNKNOWN)pData;
+	    data->size = sizeof(LPUNKNOWN);
+	    IUnknown_AddRef(data->ptr.object);
 	}
+	else
+	{
+	    data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
+	    if (data->ptr.data == NULL)
+	    {
+		HeapFree(GetProcessHeap(), 0, data);
+		return DDERR_OUTOFMEMORY;
+	    }
+	}
+
+	/* link it in */
+	data->next = This->private_data;
+	data->prev = NULL;
+	if (This->private_data)
+	    This->private_data->prev = data;
+	This->private_data = data;
+
+	return DD_OK;
     }
-    return DD_OK;
-}
+    else
+    {
+	/* I don't actually know how windows handles this case. The only
+	 * reason I don't just call FreePrivateData is because I want to
+	 * guarantee SetPrivateData working when using LPUNKNOWN or data
+	 * that is no larger than the old data. */
 
-HRESULT WINAPI IDirectDrawSurface4Impl_EnumOverlayZOrders(
-    LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPVOID lpContext,
-    LPDDENUMSURFACESCALLBACK lpfnCallback
-) {
-  ICOM_THIS(IDirectDrawSurface4Impl,iface);
-  FIXME("(%p)->(0x%08lx,%p,%p),stub!\n", This,dwFlags,
-          lpContext, lpfnCallback );
-
-  return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetClipper(
-    LPDIRECTDRAWSURFACE4 iface, LPDIRECTDRAWCLIPPER* lplpDDClipper
-) {
-  ICOM_THIS(IDirectDrawSurface4Impl,iface);
-  FIXME("(%p)->(%p),stub!\n", This, lplpDDClipper);
-
-  return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetColorKey(
-    LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY lpDDColorKey
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->(0x%08lx,%p)\n", This, dwFlags, lpDDColorKey);
-
-    if( dwFlags & DDCKEY_SRCBLT )  {
-	dwFlags &= ~DDCKEY_SRCBLT;
-	memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcBlt), sizeof( *lpDDColorKey ) );
+	return E_FAIL;
     }
-    if( dwFlags & DDCKEY_DESTBLT ) {
-	dwFlags &= ~DDCKEY_DESTBLT;
-	memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestBlt), sizeof( *lpDDColorKey ) );
-    }
-    if( dwFlags & DDCKEY_SRCOVERLAY ) {
-	dwFlags &= ~DDCKEY_SRCOVERLAY;
-	memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcOverlay), sizeof( *lpDDColorKey ) );
-    }
-    if( dwFlags & DDCKEY_DESTOVERLAY ) {
-	dwFlags &= ~DDCKEY_DESTOVERLAY;
-	memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestOverlay), sizeof( *lpDDColorKey ) );
-    }
-    if( dwFlags )
-	FIXME("unhandled dwFlags: 0x%08lx\n", dwFlags );
-    return DD_OK;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_GetFlipStatus(
-    LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
+/* SetSurfaceDesc */
+
+HRESULT WINAPI
+Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
+{
+    ICOM_THIS(IDirectDrawSurfaceImpl,iface);
+
+    TRACE("(%p)->Unlock(%p)\n",This,pRect);
+
+    This->unlock_update(This, pRect);
+    if (This->aux_unlock)
+	This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
 
     return DD_OK;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_GetPalette(
-    LPDIRECTDRAWSURFACE4 iface, LPDIRECTDRAWPALETTE* lplpDDPalette
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    TRACE("(%p)->(%p),stub!\n", This, lplpDDPalette);
-
-    if (!This->s.palette)
-	return DDERR_NOPALETTEATTACHED;
-
-    IDirectDrawPalette_AddRef( (IDirectDrawPalette*) This->s.palette );
-    *lplpDDPalette = (IDirectDrawPalette*) This->s.palette;
-    return DD_OK;
+HRESULT WINAPI
+Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
+				     LPRECT pSrcRect,
+				     LPDIRECTDRAWSURFACE7 pDstSurface,
+				     LPRECT pDstRect, DWORD dwFlags,
+				     LPDDOVERLAYFX pFX)
+{
+    return DDERR_UNSUPPORTED;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_SetOverlayPosition(
-    LPDIRECTDRAWSURFACE4 iface, LONG lX, LONG lY
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%ld,%ld),stub!\n", This, lX, lY);
-
-    return DD_OK;
+/* MSDN: "not currently implemented." */
+HRESULT WINAPI
+Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
+					    DWORD dwFlags)
+{
+    return DDERR_UNSUPPORTED;
 }
 
-HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlay(
-    LPDIRECTDRAWSURFACE4 iface, LPRECT lpSrcRect,
-    LPDIRECTDRAWSURFACE4 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags,
-    LPDDOVERLAYFX lpDDOverlayFx
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%p,%p,%p,0x%08lx,%p),stub!\n", This,
-	 lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );  
-
-    return DD_OK;
-}
- 
-HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayDisplay(
-    LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags); 
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayZOrder(
-    LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags,LPDIRECTDRAWSURFACE4 lpDDSReference
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(0x%08lx,%p),stub!\n", This, dwFlags, lpDDSReference);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetDDInterface(
-    LPDIRECTDRAWSURFACE4 iface, LPVOID* lplpDD
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%p),stub!\n", This, lplpDD);
-
-    /* Not sure about that... */
-
-    IDirectDraw_AddRef((LPDIRECTDRAW)This->s.ddraw),
-    *lplpDD = (void *) This->s.ddraw;
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_PageLock(
-    LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_PageUnlock(
-    LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_SetSurfaceDesc(
-    LPDIRECTDRAWSURFACE4 iface, LPDDSURFACEDESC lpDDSD, DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%p,0x%08lx),stub!\n", This, lpDDSD, dwFlags);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_SetPrivateData(
-    LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag, LPVOID lpData, DWORD cbSize,
-    DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%p,%p,%ld,%08lx\n", This, guidTag, lpData, cbSize, dwFlags);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetPrivateData(
-    LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag, LPVOID lpBuffer,
-    LPDWORD lpcbBufferSize
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%p,%p,%p)\n", This, guidTag, lpBuffer, lpcbBufferSize);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_FreePrivateData(
-    LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%p)\n", This, guidTag);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_GetUniquenessValue(
-    LPDIRECTDRAWSURFACE4 iface, LPDWORD lpValue
-)  {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)->(%p)\n", This, lpValue);
-
-    return DD_OK;
-}
-
-HRESULT WINAPI IDirectDrawSurface4Impl_ChangeUniquenessValue(
-    LPDIRECTDRAWSURFACE4 iface
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    FIXME("(%p)\n", This);
-
-    return DD_OK;
+HRESULT WINAPI
+Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
+					   DWORD dwFlags,
+					   LPDIRECTDRAWSURFACE7 pDDSRef)
+{
+    return DDERR_NOTAOVERLAYSURFACE;
 }
diff --git a/dlls/ddraw/dsurface/main.h b/dlls/ddraw/dsurface/main.h
new file mode 100644
index 0000000..8630964
--- /dev/null
+++ b/dlls/ddraw/dsurface/main.h
@@ -0,0 +1,215 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_MAIN_H_INCLUDED
+#define DDRAW_DSURFACE_MAIN_H_INCLUDED
+
+#include "ddraw_private.h"
+
+/* Support for IDirectDrawSurface7::Set/Get/FreePrivateData. I don't think
+ * anybody uses it for much so a good implementation is optional. */
+typedef struct PrivateData
+{
+    struct PrivateData* next;
+    struct PrivateData* prev;
+
+    GUID tag;
+    DWORD flags; /* DDSPD_* */
+    DWORD uniqueness_value;
+
+    union
+    {
+	LPVOID data;
+	LPUNKNOWN object;
+    } ptr;
+
+    DWORD size;
+} PrivateData;
+
+/* Non-interface functions */
+HRESULT
+Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				 IDirectDrawImpl* pDD,
+				 const DDSURFACEDESC2* pDDSD);
+void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This);
+
+void
+Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This);
+BOOL
+Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
+			      IDirectDrawSurfaceImpl *to);
+BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This);
+void
+Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
+				   LPCRECT pRect);
+void
+Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
+				     LPCRECT pRect);
+void
+Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This);
+void
+Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+				   IDirectDrawPaletteImpl* pal);
+void
+Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+				      IDirectDrawPaletteImpl* pal,
+				      DWORD dwStart, DWORD dwCount,
+				      LPPALETTEENTRY palent);
+HWND
+Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This);
+
+void Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				      IDirectDrawSurfaceImpl* back);
+
+#define CHECK_LOST(This)					\
+	do {							\
+		if (This->lost) return DDERR_SURFACELOST;	\
+	} while (0)
+
+#define CHECK_TEXTURE(This)					\
+	do {							\
+		if (!(This->surface_desc.ddsCaps.dwCaps2	\
+		      & DDSCAPS2_TEXTUREMANAGE))		\
+			return DDERR_INVALIDOBJECT;		\
+	} while (0)
+
+#define LOCK_OBJECT(This) do { } while (0)
+#define UNLOCK_OBJECT(This) do { } while (0)
+
+/* IDirectDrawSurface7 (partial) implementation */
+ULONG WINAPI
+Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface);
+ULONG WINAPI
+Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface);
+HRESULT WINAPI
+Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
+				      LPVOID* ppObj);
+HRESULT WINAPI
+Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
+					  LPDIRECTDRAWSURFACE7 pAttach);
+HRESULT WINAPI
+Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
+					   LPRECT pRect);
+HRESULT WINAPI
+Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
+				LPDDBLTBATCH pBatch, DWORD dwCount,
+				DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface);
+HRESULT WINAPI
+Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
+					     DWORD dwFlags,
+					     LPDIRECTDRAWSURFACE7 pAttach);
+HRESULT WINAPI
+Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
+					    LPVOID context,
+					    LPDDENUMSURFACESCALLBACK7 cb);
+HRESULT WINAPI
+Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
+					  DWORD dwFlags, LPVOID context,
+					  LPDDENUMSURFACESCALLBACK7 cb);
+HRESULT WINAPI
+Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
+			    LPDIRECTDRAWSURFACE7 override, DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface,
+				       REFGUID tag);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
+					  LPDDSCAPS2 pCaps,
+					  LPDIRECTDRAWSURFACE7* ppSurface);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface,
+				    DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface,
+			       LPDDSCAPS2 pCaps);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAWCLIPPER* ppClipper);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface,
+				   DWORD dwFlags, LPDDCOLORKEY pCKey);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface,
+				      LPVOID* pDD);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface,
+				     DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface,
+			      LPDWORD pdwMaxLOD);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
+					  LPLONG pX, LPLONG pY);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAWPALETTE* ppPalette);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
+				      LPDDPIXELFORMAT pDDPixelFormat);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
+				   LPDWORD pdwPriority);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag,
+				      LPVOID pBuffer, LPDWORD pcbBufferSize);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
+				      LPDDSURFACEDESC2 pDDSD);
+HRESULT WINAPI
+Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
+					  LPDWORD pValue);
+HRESULT WINAPI
+Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD);
+HRESULT WINAPI
+Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface);
+HRESULT WINAPI
+Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
+			    LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h);
+HRESULT WINAPI
+Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC);
+HRESULT WINAPI
+Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAWCLIPPER pDDClipper);
+HRESULT WINAPI
+Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
+				   DWORD dwFlags, LPDDCOLORKEY pCKey);
+HRESULT WINAPI
+Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD);
+HRESULT WINAPI
+Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
+					  LONG X, LONG Y);
+HRESULT WINAPI
+Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
+				  LPDIRECTDRAWPALETTE pPalette);
+HRESULT WINAPI
+Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
+				   DWORD dwPriority);
+HRESULT WINAPI
+Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
+				      REFGUID tag, LPVOID pData,
+				      DWORD cbSize, DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect);
+HRESULT WINAPI
+Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
+				     LPRECT pSrcRect,
+				     LPDIRECTDRAWSURFACE7 pDstSurface,
+				     LPRECT pDstRect, DWORD dwFlags,
+				     LPDDOVERLAYFX pFX);
+HRESULT WINAPI
+Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
+					    DWORD dwFlags);
+HRESULT WINAPI
+Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
+					   DWORD dwFlags,
+					   LPDIRECTDRAWSURFACE7 pDDSRef);
+
+#endif
diff --git a/dlls/ddraw/dsurface/thunks.c b/dlls/ddraw/dsurface/thunks.c
new file mode 100644
index 0000000..ace0417
--- /dev/null
+++ b/dlls/ddraw/dsurface/thunks.c
@@ -0,0 +1,401 @@
+/* IDirectDrawSurface3 -> IDirectDrawSurface7 thunks
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+#include "ddraw.h"
+#include "winerror.h"
+
+#include "ddcomimpl.h"
+#include "dsurface/main.h"
+#include "dsurface/thunks.h"
+
+#define CONVERT(pdds) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl,	\
+					 IDirectDrawSurface3,		\
+					 IDirectDrawSurface7,		\
+					 (pdds))
+
+#define CONVERT_REV(pdds) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl,	\
+					     IDirectDrawSurface7,	\
+					     IDirectDrawSurface3,	\
+					     (pdds))
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_QueryInterface(LPDIRECTDRAWSURFACE3 This, REFIID iid,
+				       LPVOID *ppObj)
+{
+    return IDirectDrawSurface7_QueryInterface(CONVERT(This), iid, ppObj);
+}
+
+static ULONG WINAPI
+IDirectDrawSurface3Impl_AddRef(LPDIRECTDRAWSURFACE3 This)
+{
+    return IDirectDrawSurface7_AddRef(CONVERT(This));
+}
+
+static ULONG WINAPI
+IDirectDrawSurface3Impl_Release(LPDIRECTDRAWSURFACE3 This)
+{
+    return IDirectDrawSurface7_Release(CONVERT(This));
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_AddAttachedSurface(LPDIRECTDRAWSURFACE3 This,
+					   LPDIRECTDRAWSURFACE3 pAttach)
+{
+    return IDirectDrawSurface7_AddAttachedSurface(CONVERT(This),
+						  CONVERT(pAttach));
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE3 This,
+					    LPRECT pRect)
+{
+    return IDirectDrawSurface7_AddOverlayDirtyRect(CONVERT(This), pRect);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_Blt(LPDIRECTDRAWSURFACE3 This, LPRECT prcDst,
+			    LPDIRECTDRAWSURFACE3 pSrcSurf, LPRECT prcSrc,
+			    DWORD dwFlags, LPDDBLTFX pFX)
+{
+    return IDirectDrawSurface7_Blt(CONVERT(This), prcDst, CONVERT(pSrcSurf),
+				   prcSrc, dwFlags, pFX);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_BltBatch(LPDIRECTDRAWSURFACE3 This,
+				 LPDDBLTBATCH pBatch, DWORD dwCount,
+				 DWORD dwFlags)
+{
+    return IDirectDrawSurface7_BltBatch(CONVERT(This), pBatch, dwCount,
+					dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_BltFast(LPDIRECTDRAWSURFACE3 This, DWORD x, DWORD y,
+				LPDIRECTDRAWSURFACE3 pSrcSurf, LPRECT prcSrc,
+				DWORD dwTrans)
+{
+    return IDirectDrawSurface7_BltFast(CONVERT(This), x, y, CONVERT(pSrcSurf),
+				       prcSrc, dwTrans);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_DeleteAttachedSurface(LPDIRECTDRAWSURFACE3 This,
+					      DWORD dwFlags,
+					      LPDIRECTDRAWSURFACE3 pAttached)
+{
+    return IDirectDrawSurface7_DeleteAttachedSurface(CONVERT(This), dwFlags,
+						     CONVERT(pAttached));
+}
+
+struct callback_info
+{
+    LPDDENUMSURFACESCALLBACK callback;
+    LPVOID context;
+};
+
+static HRESULT CALLBACK
+EnumCallback(LPDIRECTDRAWSURFACE7 iface, LPDDSURFACEDESC2 pDDSD,
+	     LPVOID context)
+{
+    const struct callback_info* info = context;
+
+#if 0
+    /* This is an outgoing conversion so we have to do it. */
+    DDSURFACEDESC ddsd;
+    memset(&ddsd, 0, sizeof(ddsd));
+    ddsd.dwSize = sizeof(ddsd);
+    DDRAW_Convert_DDSURFACEDESC_2_To_1(pDDSD, &ddsd);
+#endif
+
+    return info->callback((LPDIRECTDRAWSURFACE)CONVERT_REV(iface), pDDSD,
+			  info->context);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE3 This,
+					     LPVOID context,
+					     LPDDENUMSURFACESCALLBACK callback)
+{
+    struct callback_info info = { callback, context };
+    return IDirectDrawSurface7_EnumAttachedSurfaces(CONVERT(This), &info,
+						    EnumCallback);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_EnumOverlayZOrders(LPDIRECTDRAWSURFACE3 This,
+					   DWORD dwFlags, LPVOID context,
+					   LPDDENUMSURFACESCALLBACK callback)
+{
+    struct callback_info info = { callback, context };
+    return IDirectDrawSurface7_EnumOverlayZOrders(CONVERT(This), dwFlags,
+						  &info, EnumCallback);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_Flip(LPDIRECTDRAWSURFACE3 This,
+			     LPDIRECTDRAWSURFACE3 pOverride, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_Flip(CONVERT(This), CONVERT(pOverride),
+				    dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetAttachedSurface(LPDIRECTDRAWSURFACE3 This,
+					   LPDDSCAPS pCaps,
+					   LPDIRECTDRAWSURFACE3* ppAttached)
+{
+    DDSCAPS2 caps = { pCaps->dwCaps, 0, 0, 0 };
+    LPDIRECTDRAWSURFACE7 pAttached7;
+    HRESULT hr;
+
+    hr = IDirectDrawSurface7_GetAttachedSurface(CONVERT(This), &caps,
+						&pAttached7);
+    if (FAILED(hr)) return hr;
+
+    *ppAttached = CONVERT_REV(pAttached7);
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetBltStatus(LPDIRECTDRAWSURFACE3 This, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_GetBltStatus(CONVERT(This), dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetCaps(LPDIRECTDRAWSURFACE3 This, LPDDSCAPS pCaps)
+{
+    DDSCAPS2 caps;
+    HRESULT hr;
+
+    hr = IDirectDrawSurface7_GetCaps(CONVERT(This), &caps);
+    if (FAILED(hr)) return hr;
+
+    pCaps->dwCaps = caps.dwCaps;
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetClipper(LPDIRECTDRAWSURFACE3 This,
+				   LPDIRECTDRAWCLIPPER* ppClipper)
+{
+    return IDirectDrawSurface7_GetClipper(CONVERT(This), ppClipper);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetColorKey(LPDIRECTDRAWSURFACE3 This, DWORD dwFlags,
+				    LPDDCOLORKEY pCKey)
+{
+    return IDirectDrawSurface7_GetColorKey(CONVERT(This), dwFlags, pCKey);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetDC(LPDIRECTDRAWSURFACE3 This, HDC* phDC)
+{
+    return IDirectDrawSurface7_GetDC(CONVERT(This), phDC);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetFlipStatus(LPDIRECTDRAWSURFACE3 This, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_GetFlipStatus(CONVERT(This), dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetOverlayPosition(LPDIRECTDRAWSURFACE3 This, LPLONG pX,
+				       LPLONG pY)
+{
+    return IDirectDrawSurface7_GetOverlayPosition(CONVERT(This), pX, pY);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetPalette(LPDIRECTDRAWSURFACE3 This,
+				   LPDIRECTDRAWPALETTE* ppPalette)
+{
+    return IDirectDrawSurface7_GetPalette(CONVERT(This), ppPalette);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetPixelFormat(LPDIRECTDRAWSURFACE3 This,
+				       LPDDPIXELFORMAT pPixelFormat)
+{
+    return IDirectDrawSurface7_GetPixelFormat(CONVERT(This), pPixelFormat);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetSurfaceDesc(LPDIRECTDRAWSURFACE3 This,
+				       LPDDSURFACEDESC pDDSD)
+{
+    return IDirectDrawSurface7_GetSurfaceDesc(CONVERT(This),
+					      (LPDDSURFACEDESC2)pDDSD);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_Initialize(LPDIRECTDRAWSURFACE3 This, LPDIRECTDRAW pDD,
+				   LPDDSURFACEDESC pDDSD)
+{
+    return IDirectDrawSurface7_Initialize(CONVERT(This), pDD,
+					  (LPDDSURFACEDESC2)pDDSD);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_IsLost(LPDIRECTDRAWSURFACE3 This)
+{
+    return IDirectDrawSurface7_IsLost(CONVERT(This));
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_Lock(LPDIRECTDRAWSURFACE3 This, LPRECT pRect,
+			     LPDDSURFACEDESC pDDSD, DWORD dwFlags, HANDLE h)
+{
+    return IDirectDrawSurface7_Lock(CONVERT(This), pRect,
+				    (LPDDSURFACEDESC2)pDDSD, dwFlags, h);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_ReleaseDC(LPDIRECTDRAWSURFACE3 This, HDC hDC)
+{
+    return IDirectDrawSurface7_ReleaseDC(CONVERT(This), hDC);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_Restore(LPDIRECTDRAWSURFACE3 This)
+{
+    return IDirectDrawSurface7_Restore(CONVERT(This));
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_SetClipper(LPDIRECTDRAWSURFACE3 This,
+				   LPDIRECTDRAWCLIPPER pClipper)
+{
+    return IDirectDrawSurface7_SetClipper(CONVERT(This), pClipper);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_SetColorKey(LPDIRECTDRAWSURFACE3 This, DWORD dwFlags,
+				    LPDDCOLORKEY pCKey)
+{
+    return IDirectDrawSurface7_SetColorKey(CONVERT(This), dwFlags, pCKey);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_SetOverlayPosition(LPDIRECTDRAWSURFACE3 This, LONG x,
+				       LONG y)
+{
+    return IDirectDrawSurface7_SetOverlayPosition(CONVERT(This), x, y);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_SetPalette(LPDIRECTDRAWSURFACE3 This,
+				   LPDIRECTDRAWPALETTE pPalette)
+{
+    return IDirectDrawSurface7_SetPalette(CONVERT(This), pPalette);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_Unlock(LPDIRECTDRAWSURFACE3 This, LPVOID data)
+{
+    /* XXX This might be wrong as LPVOID changed to LPRECT along the way. */
+    return IDirectDrawSurface7_Unlock(CONVERT(This), data);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_UpdateOverlay(LPDIRECTDRAWSURFACE3 This, LPRECT prcSrc,
+				      LPDIRECTDRAWSURFACE3 pDstSurf,
+				      LPRECT prcDst, DWORD dwFlags,
+				      LPDDOVERLAYFX pFX)
+{
+    return IDirectDrawSurface7_UpdateOverlay(CONVERT(This), prcSrc,
+					     CONVERT(pDstSurf), prcDst,
+					     dwFlags, pFX);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE3 This,
+					     DWORD dwFlags)
+{
+    return IDirectDrawSurface7_UpdateOverlayDisplay(CONVERT(This), dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE3 This,
+					    DWORD dwFlags,
+					    LPDIRECTDRAWSURFACE3 pSurfReference)
+{
+    return IDirectDrawSurface7_UpdateOverlayZOrder(CONVERT(This), dwFlags,
+						   CONVERT(pSurfReference));
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_GetDDInterface(LPDIRECTDRAWSURFACE3 This, LPVOID* ppDD)
+{
+    return IDirectDrawSurface7_GetDDInterface(CONVERT(This), ppDD);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_PageLock(LPDIRECTDRAWSURFACE3 This, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_PageLock(CONVERT(This), dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_PageUnlock(LPDIRECTDRAWSURFACE3 This, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_PageUnlock(CONVERT(This), dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface3Impl_SetSurfaceDesc(LPDIRECTDRAWSURFACE3 This,
+				       LPDDSURFACEDESC pDDSD, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_SetSurfaceDesc(CONVERT(This),
+					      (LPDDSURFACEDESC2)pDDSD,
+					      dwFlags);
+}
+
+ICOM_VTABLE(IDirectDrawSurface3) DDRAW_IDDS3_Thunk_VTable =
+{
+    IDirectDrawSurface3Impl_QueryInterface,
+    IDirectDrawSurface3Impl_AddRef,
+    IDirectDrawSurface3Impl_Release,
+    IDirectDrawSurface3Impl_AddAttachedSurface,
+    IDirectDrawSurface3Impl_AddOverlayDirtyRect,
+    IDirectDrawSurface3Impl_Blt,
+    IDirectDrawSurface3Impl_BltBatch,
+    IDirectDrawSurface3Impl_BltFast,
+    IDirectDrawSurface3Impl_DeleteAttachedSurface,
+    IDirectDrawSurface3Impl_EnumAttachedSurfaces,
+    IDirectDrawSurface3Impl_EnumOverlayZOrders,
+    IDirectDrawSurface3Impl_Flip,
+    IDirectDrawSurface3Impl_GetAttachedSurface,
+    IDirectDrawSurface3Impl_GetBltStatus,
+    IDirectDrawSurface3Impl_GetCaps,
+    IDirectDrawSurface3Impl_GetClipper,
+    IDirectDrawSurface3Impl_GetColorKey,
+    IDirectDrawSurface3Impl_GetDC,
+    IDirectDrawSurface3Impl_GetFlipStatus,
+    IDirectDrawSurface3Impl_GetOverlayPosition,
+    IDirectDrawSurface3Impl_GetPalette,
+    IDirectDrawSurface3Impl_GetPixelFormat,
+    IDirectDrawSurface3Impl_GetSurfaceDesc,
+    IDirectDrawSurface3Impl_Initialize,
+    IDirectDrawSurface3Impl_IsLost,
+    IDirectDrawSurface3Impl_Lock,
+    IDirectDrawSurface3Impl_ReleaseDC,
+    IDirectDrawSurface3Impl_Restore,
+    IDirectDrawSurface3Impl_SetClipper,
+    IDirectDrawSurface3Impl_SetColorKey,
+    IDirectDrawSurface3Impl_SetOverlayPosition,
+    IDirectDrawSurface3Impl_SetPalette,
+    IDirectDrawSurface3Impl_Unlock,
+    IDirectDrawSurface3Impl_UpdateOverlay,
+    IDirectDrawSurface3Impl_UpdateOverlayDisplay,
+    IDirectDrawSurface3Impl_UpdateOverlayZOrder,
+    IDirectDrawSurface3Impl_GetDDInterface,
+    IDirectDrawSurface3Impl_PageLock,
+    IDirectDrawSurface3Impl_PageUnlock,
+    IDirectDrawSurface3Impl_SetSurfaceDesc
+};
diff --git a/dlls/ddraw/dsurface/thunks.h b/dlls/ddraw/dsurface/thunks.h
new file mode 100644
index 0000000..989f0a7
--- /dev/null
+++ b/dlls/ddraw/dsurface/thunks.h
@@ -0,0 +1,8 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_THUNKS_H_INCLUDED
+#define DDRAW_DSURFACE_THUNKS_H_INCLUDED
+
+extern ICOM_VTABLE(IDirectDrawSurface3) DDRAW_IDDS3_Thunk_VTable;
+
+#endif
diff --git a/dlls/ddraw/dsurface/user.c b/dlls/ddraw/dsurface/user.c
new file mode 100644
index 0000000..8504ffe
--- /dev/null
+++ b/dlls/ddraw/dsurface/user.c
@@ -0,0 +1,499 @@
+/*	User-based primary surface driver
+ *
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+#include "winerror.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "debugtools.h"
+#include "ddraw_private.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/user.h"
+#include "dsurface/wndproc.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+/* if you use OWN_WINDOW, don't use SYNC_UPDATE, or you may get trouble */
+/* #define SYNC_UPDATE */
+#define OWN_WINDOW
+
+#ifdef OWN_WINDOW
+static void User_create_own_window(IDirectDrawSurfaceImpl* This);
+static void User_destroy_own_window(IDirectDrawSurfaceImpl* This);
+#endif
+#ifndef SYNC_UPDATE
+static DWORD CALLBACK User_update_thread(LPVOID);
+#endif
+static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc);
+static void User_copy_from_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc);
+
+static ICOM_VTABLE(IDirectDrawSurface7) User_IDirectDrawSurface7_VTable;
+
+HRESULT
+User_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				 IDirectDrawImpl* pDD,
+				 const DDSURFACEDESC2* pDDSD)
+{
+    USER_PRIV_VAR(priv, This);
+    HRESULT hr;
+
+    TRACE("(%p,%p,%p)\n",This,pDD,pDDSD);
+    hr = DIB_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr)) return hr;
+
+    ICOM_INIT_INTERFACE(This, IDirectDrawSurface7,
+			User_IDirectDrawSurface7_VTable);
+
+    This->final_release = User_DirectDrawSurface_final_release;
+    This->duplicate_surface = User_DirectDrawSurface_duplicate_surface;
+
+    This->lock_update   = User_DirectDrawSurface_lock_update;
+    This->unlock_update = User_DirectDrawSurface_unlock_update;
+
+    This->flip_data   = User_DirectDrawSurface_flip_data;
+    This->flip_update = User_DirectDrawSurface_flip_update;
+
+    This->get_dc     = User_DirectDrawSurface_get_dc;
+    This->release_dc = User_DirectDrawSurface_release_dc;
+
+    This->set_palette    = User_DirectDrawSurface_set_palette;
+    This->update_palette = User_DirectDrawSurface_update_palette;
+
+    This->get_display_window = User_DirectDrawSurface_get_display_window;
+
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+#ifndef SYNC_UPDATE
+	priv->user.update_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+	priv->user.update_thread = CreateThread(NULL, 0, User_update_thread, This, 0, NULL);
+#else
+#ifdef OWN_WINDOW
+	User_create_own_window(This);
+#endif
+#endif
+    }
+
+    return DIB_DirectDrawSurface_alloc_dc(This, &priv->user.cached_dc);
+}
+
+HRESULT
+User_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+			      const DDSURFACEDESC2 *pDDSD,
+			      LPDIRECTDRAWSURFACE7 *ppSurf,
+			      IUnknown *pUnkOuter)
+{
+    IDirectDrawSurfaceImpl* This;
+    HRESULT hr;
+    assert(pUnkOuter == NULL);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(*This) + sizeof(User_DirectDrawSurfaceImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    This->private = (User_DirectDrawSurfaceImpl*)(This+1);
+
+    hr = User_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7);
+
+    return hr;
+}
+
+void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
+{
+    USER_PRIV_VAR(priv, This);
+
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+#ifndef SYNC_UPDATE
+	HANDLE event = priv->user.update_event;
+	priv->user.update_event = 0;
+	SetEvent(event);
+	TRACE("waiting for update thread to terminate...\n");
+#ifdef OWN_WINDOW
+	/* dispatch any waiting sendmessages */
+	{
+	    MSG msg;
+	    PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
+	}
+	/* to avoid deadlocks, allow SendMessages from update thread
+	 * through while we wait for it */
+	while (MsgWaitForMultipleObjects(1, &priv->user.update_thread, FALSE,
+					 INFINITE, QS_SENDMESSAGE) == WAIT_OBJECT_0+1)
+	{
+	    MSG msg;
+	    PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
+	}
+#else
+	WaitForSingleObject(priv->user.update_thread,INFINITE);
+#endif
+	TRACE("update thread terminated\n");
+	CloseHandle(priv->user.update_thread);
+#else
+#ifdef OWN_WINDOW
+	User_destroy_own_window(This);
+#endif
+#endif
+    }
+    DIB_DirectDrawSurface_free_dc(This, priv->user.cached_dc);
+    DIB_DirectDrawSurface_final_release(This);
+}
+
+void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
+					LPCRECT pRect)
+{
+    User_copy_from_screen(This, pRect);
+}
+
+void User_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
+					  LPCRECT pRect)
+{
+#ifdef SYNC_UPDATE
+    User_copy_to_screen(This, pRect);
+#else
+    USER_PRIV_VAR(priv, This);
+    SetEvent(priv->user.update_event);
+#endif
+}
+
+void User_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+					IDirectDrawPaletteImpl* pal) 
+{
+    USER_PRIV_VAR(priv, This);
+
+    if (!pal) {
+	FIXME("selecting null palette\n");
+	/* I don't think selecting GDI object 0 will work, we should select
+	 * the original palette, returned by the first SelectPalette */
+	SelectPalette(priv->user.cached_dc, 0, FALSE);
+	return;
+    }
+
+    SelectPalette(priv->user.cached_dc, pal->hpal, FALSE);
+
+    DIB_DirectDrawSurface_set_palette(This, pal);
+}
+
+void User_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+					   IDirectDrawPaletteImpl* pal,
+					   DWORD dwStart, DWORD dwCount,
+					   LPPALETTEENTRY palent)
+{
+    USER_PRIV_VAR(priv, This);
+
+    DIB_DirectDrawSurface_update_palette(This, pal, dwStart, dwCount, palent);
+    /* FIXME: realize palette on display window */
+
+#ifndef SYNC_UPDATE
+    /* with async updates, it's probably cool to force an update */
+    SetEvent(priv->user.update_event);
+#endif
+}
+
+HRESULT User_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						 LPDIRECTDRAWSURFACE7* ppDup)
+{
+    return User_DirectDrawSurface_Create(This->ddraw_owner,
+					 &This->surface_desc, ppDup, NULL);
+}
+
+void User_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				      IDirectDrawSurfaceImpl* back)
+{
+    USER_PRIV_VAR(front_priv, front);
+    USER_PRIV_VAR(back_priv, back);
+
+    {
+	HDC tmp;
+	tmp = front_priv->user.cached_dc;
+	front_priv->user.cached_dc = back_priv->user.cached_dc;
+	back_priv->user.cached_dc = tmp;
+    }
+
+    DIB_DirectDrawSurface_flip_data(front, back);
+}
+
+void User_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This)
+{
+#ifdef SYNC_UPDATE
+    assert(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
+    User_copy_to_screen(This,NULL);
+#else
+    USER_PRIV_VAR(priv, This);
+    assert(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
+    SetEvent(priv->user.update_event);
+#endif
+}
+
+HRESULT User_DirectDrawSurface_get_dc(IDirectDrawSurfaceImpl* This, HDC* phDC)
+{
+    USER_PRIV_VAR(priv, This);
+
+    *phDC = priv->user.cached_dc;
+    return S_OK;
+}
+
+HRESULT User_DirectDrawSurface_release_dc(IDirectDrawSurfaceImpl* This,
+					  HDC hDC)
+{
+    return S_OK;
+}
+
+/* Returns the window that hosts the display.
+ * *pt is set to the upper left position of the window relative to the
+ * upper left corner of the surface. */
+static HWND get_display_window(IDirectDrawSurfaceImpl* This, LPPOINT pt)
+{
+    memset(pt, 0, sizeof(*pt));
+
+    if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN)
+    {
+#ifdef OWN_WINDOW
+	USER_PRIV_VAR(priv, This);
+	SetWindowPos(priv->user.window, HWND_TOP, 0, 0, 0, 0,
+		     SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|
+		     SWP_NOREDRAW|SWP_NOSENDCHANGING|SWP_NOSIZE);
+	return priv->user.window;
+#else
+	return This->ddraw_owner->window;
+#endif
+    }
+    else
+    {
+	if (This->clipper != NULL)
+	{
+	    /* looks silly, but since we don't have the clipper locked */
+	    HWND hWnd = This->clipper->hWnd;
+
+	    if (hWnd != 0)
+	    {
+		ClientToScreen(hWnd, pt);
+		return hWnd;
+	    }
+	    else
+	    {
+		static BOOL warn = 0;
+		if (!warn++) FIXME("clipper clip lists not supported\n");
+
+		return GetDesktopWindow();
+	    }
+	}
+	else
+	{
+	    static BOOL warn = 0;
+	    if (!warn++) WARN("hosting on root\n");
+
+	    return GetDesktopWindow();
+	}
+    }
+}
+
+HWND User_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
+{
+    POINT offset;
+    return get_display_window(This, &offset);
+}
+
+#ifdef OWN_WINDOW
+static void User_create_own_window(IDirectDrawSurfaceImpl* This)
+{
+    USER_PRIV_VAR(priv, This);
+
+    if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN)
+    {
+	DirectDrawSurface_RegisterClass();
+	priv->user.window = CreateWindowExA(WS_EX_TOPMOST,
+					    "WINE_DDRAW", "DirectDraw",
+					    WS_POPUP,
+					    0, 0,
+					    This->surface_desc.dwWidth,
+					    This->surface_desc.dwHeight,
+					    GetDesktopWindow(),
+					    0, 0, This);
+	SetWindowPos(priv->user.window, HWND_TOP, 0, 0, 0, 0,
+		     SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|
+		     SWP_NOREDRAW|SWP_NOSENDCHANGING|SWP_NOSIZE|SWP_SHOWWINDOW);
+	UpdateWindow(priv->user.window);
+    }
+}
+
+static void User_destroy_own_window(IDirectDrawSurfaceImpl* This)
+{
+    USER_PRIV_VAR(priv, This);
+
+    if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN)
+    {
+	SetWindowPos(priv->user.window, 0, 0, 0, 0, 0,
+		     SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|
+		     SWP_NOREDRAW|SWP_NOSENDCHANGING|SWP_NOSIZE|SWP_HIDEWINDOW);
+	DestroyWindow(priv->user.window);
+	DirectDrawSurface_UnregisterClass();
+    }
+}
+#endif
+
+#ifndef SYNC_UPDATE
+static DWORD CALLBACK User_update_thread(LPVOID arg)
+{
+    IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)arg;
+    USER_PRIV_VAR(priv, This);
+    volatile DWORD *pActive = (volatile DWORD *)&priv->user.update_event;
+    HANDLE event = *pActive;
+
+#ifdef OWN_WINDOW
+    User_create_own_window(This);
+#endif
+
+    /* the point of this is that many games lock the primary surface
+     * multiple times per frame; this thread will then simply copy as
+     * often as it can without keeping the main thread waiting for
+     * each unlock, thus keeping the frame rate high */
+    do {
+#ifdef OWN_WINDOW
+	DWORD ret = MsgWaitForMultipleObjects(1, &event, FALSE, INFINITE, QS_ALLINPUT);
+	MSG msg;
+
+	while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+	{
+	    switch (msg.message) {
+	    case WM_PAINT:
+		DispatchMessageA(&msg);
+		break;
+	    default:
+		/* since we risk getting keyboard messages posted to us,
+		 * repost posted messages to cooperative window */
+		PostMessageA(This->ddraw_owner->window, msg.message, msg.wParam, msg.lParam);
+	    }
+	}
+#else
+	DWORD ret = WaitForSingleObject(event, INFINITE);
+#endif
+	if (ret == WAIT_OBJECT_0)
+	{
+	    if (*pActive)
+		User_copy_to_screen(This, NULL);
+	    else
+		break;
+	}
+	else if (ret != WAIT_OBJECT_0+1) break;
+    } while (TRUE);
+
+#ifdef OWN_WINDOW
+    User_destroy_own_window(This);
+#endif
+
+    return 0;
+}
+#endif
+
+static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
+{
+    /* rc is unused. We copy the whole thing. */
+
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+	POINT offset;
+	HWND hDisplayWnd;
+	HDC hDisplayDC;
+	HDC hSurfaceDC;
+
+	if (FAILED(This->get_dc(This, &hSurfaceDC)))
+	    return;
+
+	hDisplayWnd = get_display_window(This, &offset);
+	hDisplayDC = GetDCEx(hDisplayWnd, 0, DCX_CLIPSIBLINGS);
+#if 0
+	/* FIXME: this doesn't work... if users really want to run
+	 * X in 8bpp, then we need to call directly into display.drv
+	 * (or Wine's equivalent), and force a private colormap
+	 * without default entries. */
+	if (This->palette) {
+	    SelectPalette(hDisplayDC, This->palette->hpal, FALSE);
+	    RealizePalette(hDisplayDC); /* sends messages => deadlocks */
+	}
+#endif
+
+	BitBlt(hDisplayDC, 0, 0, This->surface_desc.dwWidth,
+	       This->surface_desc.dwHeight, hSurfaceDC, offset.x, offset.y,
+	       SRCCOPY);
+
+	ReleaseDC(hDisplayWnd, hDisplayDC);
+    }
+}
+
+static void User_copy_from_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
+{
+    /* rc is unused. We copy the whole thing. */
+
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+	POINT offset;
+	HWND hDisplayWnd = get_display_window(This, &offset);
+	HDC hDisplayDC = GetDC(hDisplayWnd);
+
+	BitBlt(This->hDC, offset.x, offset.y, This->surface_desc.dwWidth,
+	       This->surface_desc.dwHeight, hDisplayDC, 0, 0, SRCCOPY);
+
+	ReleaseDC(hDisplayWnd, hDisplayDC);
+    }
+}
+
+static ICOM_VTABLE(IDirectDrawSurface7) User_IDirectDrawSurface7_VTable =
+{
+    Main_DirectDrawSurface_QueryInterface,
+    Main_DirectDrawSurface_AddRef,
+    Main_DirectDrawSurface_Release,
+    Main_DirectDrawSurface_AddAttachedSurface,
+    Main_DirectDrawSurface_AddOverlayDirtyRect,
+    DIB_DirectDrawSurface_Blt,
+    Main_DirectDrawSurface_BltBatch,
+    DIB_DirectDrawSurface_BltFast,
+    Main_DirectDrawSurface_DeleteAttachedSurface,
+    Main_DirectDrawSurface_EnumAttachedSurfaces,
+    Main_DirectDrawSurface_EnumOverlayZOrders,
+    Main_DirectDrawSurface_Flip,
+    Main_DirectDrawSurface_GetAttachedSurface,
+    Main_DirectDrawSurface_GetBltStatus,
+    Main_DirectDrawSurface_GetCaps,
+    Main_DirectDrawSurface_GetClipper,
+    Main_DirectDrawSurface_GetColorKey,
+    Main_DirectDrawSurface_GetDC,
+    Main_DirectDrawSurface_GetFlipStatus,
+    Main_DirectDrawSurface_GetOverlayPosition,
+    Main_DirectDrawSurface_GetPalette,
+    Main_DirectDrawSurface_GetPixelFormat,
+    Main_DirectDrawSurface_GetSurfaceDesc,
+    Main_DirectDrawSurface_Initialize,
+    Main_DirectDrawSurface_IsLost,
+    Main_DirectDrawSurface_Lock,
+    Main_DirectDrawSurface_ReleaseDC,
+    DIB_DirectDrawSurface_Restore,
+    Main_DirectDrawSurface_SetClipper,
+    Main_DirectDrawSurface_SetColorKey,
+    Main_DirectDrawSurface_SetOverlayPosition,
+    Main_DirectDrawSurface_SetPalette,
+    Main_DirectDrawSurface_Unlock,
+    Main_DirectDrawSurface_UpdateOverlay,
+    Main_DirectDrawSurface_UpdateOverlayDisplay,
+    Main_DirectDrawSurface_UpdateOverlayZOrder,
+    Main_DirectDrawSurface_GetDDInterface,
+    Main_DirectDrawSurface_PageLock,
+    Main_DirectDrawSurface_PageUnlock,
+    DIB_DirectDrawSurface_SetSurfaceDesc,
+    Main_DirectDrawSurface_SetPrivateData,
+    Main_DirectDrawSurface_GetPrivateData,
+    Main_DirectDrawSurface_FreePrivateData,
+    Main_DirectDrawSurface_GetUniquenessValue,
+    Main_DirectDrawSurface_ChangeUniquenessValue,
+    Main_DirectDrawSurface_SetPriority,
+    Main_DirectDrawSurface_GetPriority,
+    Main_DirectDrawSurface_SetLOD,
+    Main_DirectDrawSurface_GetLOD
+};
diff --git a/dlls/ddraw/dsurface/user.h b/dlls/ddraw/dsurface/user.h
new file mode 100644
index 0000000..c13922d
--- /dev/null
+++ b/dlls/ddraw/dsurface/user.h
@@ -0,0 +1,58 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_USER_H_INCLUDED
+#define DDRAW_DSURFACE_USER_H_INCLUDED
+
+#define USER_PRIV(surf) ((User_DirectDrawSurfaceImpl*)((surf)->private))
+
+#define USER_PRIV_VAR(name,surf) \
+	User_DirectDrawSurfaceImpl* name = USER_PRIV(surf)
+
+struct User_DirectDrawSurfaceImpl_Part
+{
+    HWND window;
+    HDC cached_dc;
+    HANDLE update_thread, update_event;
+};
+
+typedef struct
+{
+    struct DIB_DirectDrawSurfaceImpl_Part dib;
+    struct User_DirectDrawSurfaceImpl_Part user;
+} User_DirectDrawSurfaceImpl;
+
+HRESULT
+User_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				 IDirectDrawImpl* pDD,
+				 const DDSURFACEDESC2* pDDSD);
+
+HRESULT
+User_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+			      const DDSURFACEDESC2 *pDDSD,
+			      LPDIRECTDRAWSURFACE7 *ppSurf,
+			      IUnknown *pUnkOuter);
+
+void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This);
+
+void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
+					LPCRECT pRect);
+void User_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
+					  LPCRECT pRect);
+void User_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+					IDirectDrawPaletteImpl* pal);
+void User_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+					   IDirectDrawPaletteImpl* pal,
+					   DWORD dwStart, DWORD dwCount,
+					   LPPALETTEENTRY palent);
+HRESULT User_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						 LPDIRECTDRAWSURFACE7* ppDup);
+void User_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				      IDirectDrawSurfaceImpl* back);
+void User_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This);
+HWND User_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This);
+
+HRESULT User_DirectDrawSurface_get_dc(IDirectDrawSurfaceImpl* This, HDC* phDC);
+HRESULT User_DirectDrawSurface_release_dc(IDirectDrawSurfaceImpl* This,
+					  HDC hDC);
+
+#endif
diff --git a/dlls/ddraw/dsurface/wndproc.c b/dlls/ddraw/dsurface/wndproc.c
new file mode 100644
index 0000000..4a3a1b6
--- /dev/null
+++ b/dlls/ddraw/dsurface/wndproc.c
@@ -0,0 +1,85 @@
+/*	User-based primary surface driver
+ *
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+#include "winerror.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "debugtools.h"
+#include "ddraw_private.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static LRESULT WINAPI DirectDrawSurface_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+void DirectDrawSurface_RegisterClass(void)
+{
+    WNDCLASSA wc;
+    memset(&wc, 0, sizeof(wc));
+    wc.lpfnWndProc = DirectDrawSurface_WndProc;
+    wc.cbWndExtra  = sizeof(IDirectDrawSurfaceImpl*);
+    wc.hCursor     = (HCURSOR)IDC_ARROWA;
+    wc.lpszClassName = "WINE_DDRAW";
+    RegisterClassA(&wc);
+}
+
+void DirectDrawSurface_UnregisterClass(void)
+{
+    UnregisterClassA("WINE_DDRAW", 0);
+}
+
+static LRESULT WINAPI DirectDrawSurface_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    IDirectDrawSurfaceImpl *This;
+    LRESULT ret;
+
+    This = (IDirectDrawSurfaceImpl *)GetWindowLongA(hwnd, 0);
+    if (This) {
+	HWND window = This->ddraw_owner->window;
+
+	switch (msg) {
+	case WM_DESTROY:
+	case WM_NCDESTROY:
+	case WM_SHOWWINDOW:
+	case WM_WINDOWPOSCHANGING:
+	case WM_WINDOWPOSCHANGED:
+	case WM_SIZE:
+	case WM_MOVE:
+	case WM_ERASEBKGND:
+	    /* since we're pretending fullscreen,
+	     * let's not pass these on to the app */
+	    ret = DefWindowProcA(hwnd, msg, wParam, lParam);
+	    break;
+	case WM_NCHITTEST:
+	    ret = HTCLIENT;
+	    break;
+	case WM_MOUSEACTIVATE:
+	    ret = MA_NOACTIVATE;
+	    break;
+	case WM_PAINT:
+	    {
+		PAINTSTRUCT ps;
+		HDC dc = BeginPaint(hwnd, &ps);
+		/* call User_copy_to_screen? */
+		EndPaint(hwnd, &ps);
+		ret = 0;
+	    }
+	    break;
+	default:
+	    ret = window ? SendMessageA(window, msg, wParam, lParam)
+			 : DefWindowProcA(hwnd, msg, wParam, lParam);
+	}
+    } else {
+	if (msg == WM_CREATE) {
+	    CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
+	    This = (IDirectDrawSurfaceImpl *)cs->lpCreateParams;
+	    SetWindowLongA(hwnd, 0, (LONG)This);
+	}
+	ret = DefWindowProcA(hwnd, msg, wParam, lParam);
+    }
+    return ret;
+}
diff --git a/dlls/ddraw/dsurface/wndproc.h b/dlls/ddraw/dsurface/wndproc.h
new file mode 100644
index 0000000..f83548b
--- /dev/null
+++ b/dlls/ddraw/dsurface/wndproc.h
@@ -0,0 +1,9 @@
+/* Copyright 2000 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_WNDPROC_H_INCLUDED
+#define DDRAW_DSURFACE_WNDPROC_H_INCLUDED
+
+void DirectDrawSurface_RegisterClass(void);
+void DirectDrawSurface_UnregisterClass(void);
+
+#endif
diff --git a/dlls/ddraw/dsurface/x11.c b/dlls/ddraw/dsurface/x11.c
deleted file mode 100644
index 684b10b..0000000
--- a/dlls/ddraw/dsurface/x11.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/*		DirectDrawSurface Xlib implementation
- *
- * Copyright 1997-2000 Marcus Meissner
- * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
- */
-#include "config.h"
-#include "winerror.h"
-
-#include <unistd.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "options.h"
-#include "debugtools.h"
-#include "x11_private.h"
-#include "bitmap.h"
-#include "win.h"
-#include "d3d.h"
-
-#ifdef HAVE_OPENGL
-/* for d3d texture stuff */
-# include "mesa_private.h"
-#endif
-
-DEFAULT_DEBUG_CHANNEL(ddraw);
-
-#define VISIBLE(x) (SDDSCAPS(x) & (DDSCAPS_VISIBLE|DDSCAPS_PRIMARYSURFACE))
-
-#define DDPRIVATE(x) x11_dd_private *ddpriv = ((x11_dd_private*)(x)->d->private)
-#define DPPRIVATE(x) x11_dp_private *dppriv = ((x11_dp_private*)(x)->private)
-#define DSPRIVATE(x) x11_ds_private *dspriv = ((x11_ds_private*)(x)->private)
-
-static BYTE Xlib_TouchData(LPVOID data)
-{
-    /* this is a function so it doesn't get optimized out */
-    return *(BYTE*)data;
-}
-
-/******************************************************************************
- *		IDirectDrawSurface methods
- *
- * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
- * DDS and DDS2 use those functions. (Function calls did not change (except
- * using different DirectDrawSurfaceX version), just added flags and functions)
- */
-HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_QueryInterface(
-    LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-
-    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
-    
-    /* All DirectDrawSurface versions (1, 2, 3 and 4) use
-     * the same interface. And IUnknown does that too of course.
-     */
-    if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid )	||
-	 IsEqualGUID( &IID_IDirectDrawSurface3, refiid )	||
-	 IsEqualGUID( &IID_IDirectDrawSurface2, refiid )	||
-	 IsEqualGUID( &IID_IDirectDrawSurface,  refiid )	||
-	 IsEqualGUID( &IID_IUnknown,            refiid )
-    ) {
-	    *obj = This;
-	    IDirectDrawSurface4_AddRef(iface);
-
-	    TRACE("  Creating IDirectDrawSurface interface (%p)\n", *obj);
-	    return S_OK;
-    }
-#ifdef HAVE_OPENGL
-    if ( IsEqualGUID( &IID_IDirect3DTexture2, refiid ) ) {
-	/* Texture interface */
-	*obj = d3dtexture2_create(This);
-	IDirectDrawSurface4_AddRef(iface);
-	TRACE("  Creating IDirect3DTexture2 interface (%p)\n", *obj);
-	return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirect3DTexture, refiid ) ) {
-	/* Texture interface */
-	*obj = d3dtexture_create(This);
-	IDirectDrawSurface4_AddRef(iface);
-	TRACE("  Creating IDirect3DTexture interface (%p)\n", *obj);
-	return S_OK;
-    }
-#else
-    if ( IsEqualGUID( &IID_IDirect3DTexture2, refiid ) ||
-         IsEqualGUID( &IID_IDirect3DTexture, refiid )
-       )
-    {
-       ERR( "Cannot provide 3D support without OpenGL/Mesa installed\n" );
-    }
-#endif /* HAVE_OPENGL */
-    FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
-    return OLE_E_ENUM_NOMORE;
-}
-
-HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Lock(
-    LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DSPRIVATE(This);
-    DDPRIVATE(This->s.ddraw);
-
-    /* DO NOT AddRef the surface! Lock/Unlock are NOT guaranteed to come in 
-     * matched pairs! - Marcus Meissner 20000509 */
-    TRACE("(%p)->Lock(%p,%p,%08lx,%08lx) ret=%p\n",This,lprect,lpddsd,flags,(DWORD)hnd,__builtin_return_address(0));
-    if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
-	WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
-		     This,lprect,lpddsd,flags,(DWORD)hnd);
-
-    /* First, copy the Surface description */
-    *lpddsd = This->s.surface_desc;
-    TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
-	  lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
-
-    /* If asked only for a part, change the surface pointer */
-    if (lprect) {
-	TRACE("	lprect: %dx%d-%dx%d\n",
-		lprect->top,lprect->left,lprect->bottom,lprect->right
-	);
-	if ((lprect->top < 0) ||
-	    (lprect->left < 0) ||
-	    (lprect->bottom < 0) ||
-	    (lprect->right < 0)) {
-	  ERR(" Negative values in LPRECT !!!\n");
-	  return DDERR_INVALIDPARAMS;
-	}
-	lpddsd->u1.lpSurface=(LPVOID)((char*)This->s.surface_desc.u1.lpSurface+
-		(lprect->top*This->s.surface_desc.lPitch) +
-		lprect->left*GET_BPP(This->s.surface_desc));
-    } else
-	assert(This->s.surface_desc.u1.lpSurface);
-    /* wait for any previous operations to complete */
-#ifdef HAVE_LIBXXSHM
-    if (dspriv->info.image && VISIBLE(This) && ddpriv->xshm_active) {
-/*
-	int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
-	if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
-*/
-	X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
-    }
-#endif
-
-    /* If part of a visible 'clipped' surface, copy what is seen on the
-       screen to the surface */
-    if ((dspriv->info.image && VISIBLE(This)) &&
-	(This->s.lpClipper)) {
-          HWND hWnd = ((IDirectDrawClipperImpl *) This->s.lpClipper)->hWnd;
-	  WND *wndPtr = WIN_FindWndPtr(hWnd);
-	  Drawable drawable = X11DRV_WND_GetXWindow(wndPtr);
-	  int width = wndPtr->rectClient.right - wndPtr->rectClient.left;
-	  int height = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
-	  /* Now, get the source / destination coordinates */
-	  int dest_x = wndPtr->rectClient.left;
-	  int dest_y = wndPtr->rectClient.top;
-
-	  if (!drawable) { /* we are running in -desktop mode */
-	      drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
-	      /* FIXME: not sure whether these are the right offsets */
-	      dest_x+=wndPtr->rectWindow.left;
-	      dest_y+=wndPtr->rectWindow.top;
-	      WIN_ReleaseDesktop();
-	  }
-
-	  TSXGetSubImage(display, drawable, 0, 0, width, height, 0xFFFFFFFF,
-		       ZPixmap, dspriv->info.image, dest_x, dest_y);
-	  
-	  WIN_ReleaseWndPtr(wndPtr);
-    }
-    
-    return DD_OK;
-}
-
-static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
-  DSPRIVATE(This);
-  DDPRIVATE(This->s.ddraw);
-  Drawable drawable = ddpriv->drawable;
-  POINT adjust[2] = {{0, 0}, {0, 0}};
-  SIZE imgsiz;
-
-  /* Get XImage size */
-  imgsiz.cx = dspriv->info.image->width;
-  imgsiz.cy = dspriv->info.image->height;
-
-  if (This->s.lpClipper) {
-    HWND hWnd = ((IDirectDrawClipperImpl *) This->s.lpClipper)->hWnd;
-    SIZE csiz;
-    WND *wndPtr = WIN_FindWndPtr(hWnd);
-    drawable = X11DRV_WND_GetXWindow(wndPtr);
-    
-    MapWindowPoints(hWnd, 0, adjust, 2);
-
-    imgsiz.cx -= adjust[0].x;
-    imgsiz.cy -= adjust[0].y;
-    /* (note: the rectWindow here should be the X window's interior rect, in
-     *  case anyone thinks otherwise while rewriting managed mode) */
-    adjust[1].x -= wndPtr->rectWindow.left;
-    adjust[1].y -= wndPtr->rectWindow.top;
-    csiz.cx = wndPtr->rectClient.right - wndPtr->rectClient.left;
-    csiz.cy = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
-    if (csiz.cx < imgsiz.cx) imgsiz.cx = csiz.cx;
-    if (csiz.cy < imgsiz.cy) imgsiz.cy = csiz.cy;
-    
-    TRACE("adjust: hwnd=%08x, surface %ldx%ld, drawable %ldx%ld\n", hWnd,
-	  adjust[0].x, adjust[0].y,
-	  adjust[1].x,adjust[1].y);
-    
-    WIN_ReleaseWndPtr(wndPtr);
-  }
-
-  if (!drawable) {
-    WND *tmpWnd = WIN_FindWndPtr(This->s.ddraw->d->window);
-    drawable = X11DRV_WND_GetXWindow(tmpWnd);
-    WIN_ReleaseWndPtr(tmpWnd);
-
-    /* We don't have a context for this window. Host off the desktop */
-    if( !drawable ) {
-	FIXME("Have to use Desktop Root Window??? Bummer.\n");
-	drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
-	WIN_ReleaseDesktop();
-    }
-    ddpriv->drawable = drawable;
-  }
-  
-  if (This->s.ddraw->d->pixel_convert != NULL)
-    This->s.ddraw->d->pixel_convert(This->s.surface_desc.u1.lpSurface,
-				   dspriv->info.image->data,
-				   This->s.surface_desc.dwWidth,
-				   This->s.surface_desc.dwHeight,
-				   This->s.surface_desc.lPitch,
-				   This->s.palette);
-
-  /* if the DIB section is in GdiMod state, we must
-   * touch the surface to get any updates from the DIB */
-  Xlib_TouchData(dspriv->info.image->data);
-#ifdef HAVE_LIBXXSHM
-    if (ddpriv->xshm_active) {
-/*
-	X11DRV_EVENT_WaitReplaceShmCompletion( &(ddpriv->xshm_compl), This->s.ddraw->d.drawable );
-*/
-	/* let WaitShmCompletions track 'em for now */
-	/* (you may want to track it again whenever you implement DX7's partial
-	* surface locking, where threads have concurrent access) */
-	X11DRV_EVENT_PrepareShmCompletion( ddpriv->drawable );
-	TSXShmPutImage(display,
-		       drawable,
-		       DefaultGCOfScreen(X11DRV_GetXScreen()),
-		       dspriv->info.image,
-		       adjust[0].x, adjust[0].y, adjust[1].x, adjust[1].y,
-		       imgsiz.cx, imgsiz.cy,
-		       True
-		       );
-	/* make sure the image is transferred ASAP */
-	TSXFlush(display);
-    } else
-#endif
-	TSXPutImage(display,
-		    drawable,
-		    DefaultGCOfScreen(X11DRV_GetXScreen()),
-		    dspriv->info.image,
-		    adjust[0].x, adjust[0].y, adjust[1].x, adjust[1].y,
-		    imgsiz.cx, imgsiz.cy
-		    );
-}
-
-#ifdef HAVE_XVIDEO
-static void Xlib_copy_overlay_on_screen(IDirectDrawSurface4Impl* This) {
-  DSPRIVATE(This);
-  DDPRIVATE(This->s.ddraw);
-  Drawable drawable = ddpriv->drawable;
-
-  if (!drawable) {
-    WND *tmpWnd = WIN_FindWndPtr(This->s.ddraw->d->window);
-    drawable = X11DRV_WND_GetXWindow(tmpWnd);
-    WIN_ReleaseWndPtr(tmpWnd);
-
-    /* We don't have a context for this window. Host off the desktop */
-    if( !drawable ) {
-	FIXME("Have to use Desktop Root Window??? Bummer.\n");
-	drawable = X11DRV_WND_GetXWindow(WIN_GetDesktop());
-	WIN_ReleaseDesktop();
-    }
-    ddpriv->drawable = drawable;
-  }
-
-#ifdef HAVE_LIBXXSHM
-    if (ddpriv->xshm_active) {
-	/* let WaitShmCompletions track 'em for now */
-	/* (you may want to track it again whenever you implement DX7's partial
-	* surface locking, where threads have concurrent access) */
-	X11DRV_EVENT_PrepareShmCompletion( ddpriv->drawable );
-	TSXvShmPutImage(display, ddpriv->port_id, drawable, DefaultGCOfScreen(X11DRV_GetXScreen()),
-			dspriv->info.overlay.image,
-			dspriv->info.overlay.src_rect.left, dspriv->info.overlay.src_rect.top,
-			dspriv->info.overlay.src_rect.right - dspriv->info.overlay.src_rect.left,
-			dspriv->info.overlay.src_rect.bottom - dspriv->info.overlay.src_rect.top,
-			dspriv->info.overlay.dst_rect.left, dspriv->info.overlay.dst_rect.top,
-			dspriv->info.overlay.dst_rect.right - dspriv->info.overlay.dst_rect.left,
-			dspriv->info.overlay.dst_rect.bottom - dspriv->info.overlay.dst_rect.top,
-			True);
-	/* make sure the image is transferred ASAP */
-	TSXFlush(display);
-    } else
-#endif
-      TSXvPutImage(display, ddpriv->port_id, drawable, DefaultGCOfScreen(X11DRV_GetXScreen()),
-		   dspriv->info.overlay.image,
-		   dspriv->info.overlay.src_rect.left, dspriv->info.overlay.src_rect.top,
-		   dspriv->info.overlay.src_rect.right - dspriv->info.overlay.src_rect.left,
-		   dspriv->info.overlay.src_rect.bottom - dspriv->info.overlay.src_rect.top,
-		   dspriv->info.overlay.dst_rect.left, dspriv->info.overlay.dst_rect.top,
-		   dspriv->info.overlay.dst_rect.right - dspriv->info.overlay.dst_rect.left,
-		   dspriv->info.overlay.dst_rect.bottom - dspriv->info.overlay.dst_rect.top);
-}
-#endif
-
-HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Unlock(
-    LPDIRECTDRAWSURFACE4 iface,LPVOID surface
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DDPRIVATE(This->s.ddraw);
-    DSPRIVATE(This);
-    TRACE("(%p)->Unlock(%p)\n",This,surface);
-
-    /*if (!This->s.ddraw->d.paintable)
-	return DD_OK; */
-
-    /* Only redraw the screen when unlocking the buffer that is on screen */
-    if (dspriv->info.image && VISIBLE(This)) {
-	Xlib_copy_surface_on_screen(This);
-	if (This->s.palette) {
-    	    DPPRIVATE(This->s.palette);
-	    if(dppriv->cm)
-		TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
-	}
-    } else if (dspriv->is_overlay) {
-      /* Case of an overlay surface */
-#ifdef HAVE_XVIDEO
-      if (dspriv->info.overlay.shown)
-	Xlib_copy_overlay_on_screen(This);
-#else
-      ERR("Why was this code activated WITHOUT XVideo support ?\n");
-#endif
-    } 
-    /* DO NOT Release the surface! Lock/Unlock are NOT guaranteed to come in 
-     * matched pairs! - Marcus Meissner 20000509 */
-    return DD_OK;
-}
-
-HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    XImage	*image;
-    DDPRIVATE(This->s.ddraw);
-    DSPRIVATE(This);
-    x11_ds_private	*fspriv;
-    LPBYTE	surf;
-    IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
-
-    TRACE("(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
-    if ((!This->s.ddraw->d->paintable) && (dspriv->is_overlay == FALSE))
-	return DD_OK;
-    
-    iflipto = _common_find_flipto(This,iflipto);
-    fspriv = (x11_ds_private*)iflipto->private;
-
-    /* We need to switch the lowlevel surfaces, for xlib this is: */
-    /* The surface pointer */
-    surf				= This->s.surface_desc.u1.lpSurface;
-    This->s.surface_desc.u1.lpSurface	= iflipto->s.surface_desc.u1.lpSurface;
-    iflipto->s.surface_desc.u1.lpSurface	= surf;
-
-    /* the associated ximage
-
-       NOTE : for XVideo, the pointer to the XvImage is at the same position
-              in memory than the standard XImage. This means that this code
-	      still works :-)
-    */
-    image		= dspriv->info.image;
-    dspriv->info.image	= fspriv->info.image;
-    fspriv->info.image	= image;
-
-    if (dspriv->opengl_flip) {
-#ifdef HAVE_OPENGL
-      ENTER_GL();
-      glXSwapBuffers(display, ddpriv->drawable);
-      LEAVE_GL();
-#endif
-    } else if (dspriv->is_overlay) {
-#ifdef HAVE_XVIDEO
-      if (dspriv->info.overlay.shown)
-	Xlib_copy_overlay_on_screen(This);
-#else
-      ERR("Why was this code activated WITHOUT XVideo support ?\n");
-#endif
-    } else {
-#ifdef HAVE_LIBXXSHM
-      if (ddpriv->xshm_active) {
-	/*
-	   int compl = InterlockedExchange( &(ddpriv->xshm_compl), 0 );
-	   if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
-	   */
-	X11DRV_EVENT_WaitShmCompletions( ddpriv->drawable );
-      }
-#endif
-      Xlib_copy_surface_on_screen(This);
-      if (iflipto->s.palette) {
-        DPPRIVATE(iflipto->s.palette);
-	if (dppriv->cm)
-	  TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
-      }
-    }
-    return DD_OK;
-}
-
-/* The IDirectDrawSurface4::SetPalette method attaches the specified
- * DirectDrawPalette object to a surface. The surface uses this palette for all
- * subsequent operations. The palette change takes place immediately.
- */
-HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_SetPalette(
-    LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
-) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DDPRIVATE(This->s.ddraw);
-    IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
-    x11_dp_private	*dppriv;
-    int i;
-
-    TRACE("(%p)->(%p)\n",This,ipal);
-
-    if (ipal == NULL) {
-	if( This->s.palette != NULL )
-	    IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
-	This->s.palette = ipal;
-	return DD_OK;
-    }
-    dppriv = (x11_dp_private*)ipal->private;
-
-    if (!dppriv->cm &&
-	(This->s.ddraw->d->screen_pixelformat.u.dwRGBBitCount<=8)
-    ) {
-	dppriv->cm = TSXCreateColormap(
-	    display,
-	    ddpriv->drawable,
-	    DefaultVisualOfScreen(X11DRV_GetXScreen()),
-	    AllocAll
-	);
-	if (!Options.managed)
-	    TSXInstallColormap(display,dppriv->cm);
-
-	for (i=0;i<256;i++) {
-	    XColor xc;
-
-	    xc.red		= ipal->palents[i].peRed<<8;
-	    xc.blue		= ipal->palents[i].peBlue<<8;
-	    xc.green	= ipal->palents[i].peGreen<<8;
-	    xc.flags	= DoRed|DoBlue|DoGreen;
-	    xc.pixel	= i;
-	    TSXStoreColor(display,dppriv->cm,&xc);
-	}
-	TSXInstallColormap(display,dppriv->cm);
-    }
-    /* According to spec, we are only supposed to 
-     * AddRef if this is not the same palette.
-     */
-    if ( This->s.palette != ipal ) {
-	if( ipal != NULL )
-	    IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
-	if( This->s.palette != NULL )
-	    IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
-	This->s.palette = ipal; 
-	/* Perform the refresh, only if a palette was created */
-	if (dppriv->cm)
-	  TSXSetWindowColormap(display,ddpriv->drawable,dppriv->cm);
-
-	if (This->s.hdc != 0) {
-	    /* hack: set the DIBsection color map */
-	    BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
-	    X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
-	    dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	    GDI_ReleaseObj(This->s.DIBsection);
-	}
-    }
-    return DD_OK;
-}
-
-ULONG WINAPI Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DSPRIVATE(This);
-    DDPRIVATE(This->s.ddraw);
-
-    TRACE( "(%p)->() decrementing from %lu.\n", This, This->ref );
-    if (--(This->ref))
-    	return This->ref;
-
-    IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
-
-    /* This frees the program-side surface. In some cases it had been
-     * allocated with MEM_SYSTEM, so it does not get 'really' freed
-     */
-    VirtualFree(This->s.surface_desc.u1.lpSurface, 0, MEM_RELEASE);
-
-    /* Now free the XImages and the respective screen-side surfaces */
-    if (dspriv->info.image != NULL) {
-	if (dspriv->info.image->data != This->s.surface_desc.u1.lpSurface)
-	    VirtualFree(dspriv->info.image->data, 0, MEM_RELEASE);
-#ifdef HAVE_LIBXXSHM
-	if (ddpriv->xshm_active) {
-	    TSXShmDetach(display, &(dspriv->shminfo));
-	    if (This->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
-	      TSXFree(dspriv->info.image);
-	    } else {
-	      TSXDestroyImage(dspriv->info.image);
-	    }
-	    shmdt(dspriv->shminfo.shmaddr);
-	} else 
-#endif
-	{
-	  if (This->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY) {
-	    TSXFree(dspriv->info.image);
-	  } else {
-	    /* normal X Image memory was never allocated by X, but always by 
-	     * ourselves -> Don't let X free our imagedata.
-	     */
-	    dspriv->info.image->data = NULL;
-	    TSXDestroyImage(dspriv->info.image);
-	  }
-	}
-	dspriv->info.image = 0;
-    }
-
-    if (This->s.palette)
-	IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
-
-    /* Free the DIBSection (if any) */
-    if (This->s.hdc != 0) {
-	/* hack: restore the original DIBsection color map */
-	BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
-	X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
-	dib->colorMap = dspriv->oldDIBmap;
-	GDI_ReleaseObj(This->s.DIBsection);
-
-	SelectObject(This->s.hdc, This->s.holdbitmap);
-	DeleteDC(This->s.hdc);
-	DeleteObject(This->s.DIBsection);
-    }
-
-    /* Free the clipper if present */
-    if(This->s.lpClipper)
-	IDirectDrawClipper_Release(This->s.lpClipper);
-    HeapFree(GetProcessHeap(),0,This->private);
-    HeapFree(GetProcessHeap(),0,This);
-    return S_OK;
-}
-
-HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
-    ICOM_THIS(IDirectDrawSurface4Impl,iface);
-    DSPRIVATE(This);
-    int was_ok = This->s.hdc != 0;
-    HRESULT result = IDirectDrawSurface4Impl_GetDC(iface,lphdc);
-    if (This->s.hdc && !was_ok) {
-	/* hack: take over the DIBsection color map */
-	BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
-	X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
-	dspriv->oldDIBmap = dib->colorMap;
-	dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	GDI_ReleaseObj(This->s.DIBsection);
-    }
-    return result;
-}
-
-#ifdef HAVE_XVIDEO
-typedef struct {
-  BOOL shown;
-  LPRECT src_rect;
-  LPRECT dst_rect;
-  LPDIRECTDRAWSURFACE dest_surface;
-} UpdateOverlayEnumerate;
-
-static HRESULT WINAPI enum_func(LPDIRECTDRAWSURFACE lpDDSurface,
-				LPDDSURFACEDESC lpDDSurfaceDesc,  
-				LPVOID lpContext) {
-  ICOM_THIS(IDirectDrawSurface4Impl,lpDDSurface);
-  DSPRIVATE(This);
-  UpdateOverlayEnumerate *ctx = (UpdateOverlayEnumerate *) lpContext;
-
-  if ((lpDDSurfaceDesc->ddsCaps.dwCaps) & DDSCAPS_BACKBUFFER) {
-    TRACE("Upgrading surface %p\n", lpDDSurface);
-
-    if (ctx->shown) {
-      dspriv->info.overlay.shown = TRUE;
-      dspriv->info.overlay.src_rect = *(ctx->src_rect);
-      dspriv->info.overlay.dst_rect = *(ctx->dst_rect);
-      dspriv->info.overlay.dest_surface = ctx->dest_surface;
-    } else {
-      dspriv->info.overlay.shown = FALSE;
-    }
-  }
-  
-  return DDENUMRET_OK;
-}
-#endif
-
-HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_UpdateOverlay(
-    LPDIRECTDRAWSURFACE4 iface, LPRECT lpSrcRect,
-    LPDIRECTDRAWSURFACE4 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags,
-    LPDDOVERLAYFX lpDDOverlayFx
-) {
-  ICOM_THIS(IDirectDrawSurface4Impl,iface);
-#ifdef HAVE_XVIDEO
-  DSPRIVATE(This);
-  DDPRIVATE(This->s.ddraw);
-
-  if (ddpriv->xvideo_active) {
-    TRACE("(%p)->(%p,%p,%p,0x%08lx,%p)\n", This,
-	  lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );
-
-    if (TRACE_ON(ddraw)) {
-      DPRINTF(" - dwFlags : ");
-      _dump_DDOVERLAY(dwFlags);
-      
-      if (lpSrcRect)  DPRINTF(" - src  rectangle :%dx%d-%dx%d\n",lpSrcRect->left,lpSrcRect->top,
-			      lpSrcRect->right,lpSrcRect->bottom);
-      if (lpDestRect) DPRINTF(" - dest rectangle :%dx%d-%dx%d\n",lpDestRect->left,lpDestRect->top,
-			      lpDestRect->right,lpDestRect->bottom);
-    }
-    
-    if (dwFlags & DDOVER_SHOW) {
-      UpdateOverlayEnumerate ctx;
-      
-      dwFlags &= ~DDOVER_SHOW;
-
-      if ((lpSrcRect == NULL) || (lpDestRect == NULL)) {
-	FIXME("This is NOT supported yet...\n");
-	return DD_OK;
-      }
-      
-      /* Set the shown BOOL to TRUE and update the rectangles */
-      dspriv->info.overlay.shown = TRUE;
-      dspriv->info.overlay.src_rect = *lpSrcRect;
-      dspriv->info.overlay.dst_rect = *lpDestRect;
-      dspriv->info.overlay.dest_surface = (LPDIRECTDRAWSURFACE) lpDDDestSurface;
-
-      /* Now the same for the backbuffers, except that they are NOT shown */
-      ctx.shown = FALSE;
-      ctx.src_rect = lpSrcRect;
-      ctx.dst_rect = lpDestRect;
-      ctx.dest_surface = (LPDIRECTDRAWSURFACE) lpDDDestSurface;
-
-      IDirectDrawSurface4Impl_EnumAttachedSurfaces(iface, &ctx, enum_func);
-    } else if (dwFlags & DDOVER_HIDE) {
-      UpdateOverlayEnumerate ctx;
-      
-      dwFlags &= ~DDOVER_HIDE;
-
-      /* Set the shown BOOL to FALSE for all overlays */
-      dspriv->info.overlay.shown = FALSE;
-      ctx.shown = FALSE;
-      IDirectDrawSurface4Impl_EnumAttachedSurfaces(iface, &ctx, enum_func);
-    }
-
-    if (dwFlags && TRACE_ON(ddraw)) {
-      WARN("Unsupported flags : ");
-      _dump_DDOVERLAY(dwFlags);   
-    }
-  } else
-#endif
-    FIXME("(%p)->(%p,%p,%p,0x%08lx,%p) not supported without XVideo !\n", This,
-	  lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );  
-
-  return DD_OK;
-}
-
-ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt = 
-{
-    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-    Xlib_IDirectDrawSurface4Impl_QueryInterface,
-    IDirectDrawSurface4Impl_AddRef,
-    Xlib_IDirectDrawSurface4Impl_Release,
-    IDirectDrawSurface4Impl_AddAttachedSurface,
-    IDirectDrawSurface4Impl_AddOverlayDirtyRect,
-    IDirectDrawSurface4Impl_Blt,
-    IDirectDrawSurface4Impl_BltBatch,
-    IDirectDrawSurface4Impl_BltFast,
-    IDirectDrawSurface4Impl_DeleteAttachedSurface,
-    IDirectDrawSurface4Impl_EnumAttachedSurfaces,
-    IDirectDrawSurface4Impl_EnumOverlayZOrders,
-    Xlib_IDirectDrawSurface4Impl_Flip,
-    IDirectDrawSurface4Impl_GetAttachedSurface,
-    IDirectDrawSurface4Impl_GetBltStatus,
-    IDirectDrawSurface4Impl_GetCaps,
-    IDirectDrawSurface4Impl_GetClipper,
-    IDirectDrawSurface4Impl_GetColorKey,
-    Xlib_IDirectDrawSurface4Impl_GetDC,
-    IDirectDrawSurface4Impl_GetFlipStatus,
-    IDirectDrawSurface4Impl_GetOverlayPosition,
-    IDirectDrawSurface4Impl_GetPalette,
-    IDirectDrawSurface4Impl_GetPixelFormat,
-    IDirectDrawSurface4Impl_GetSurfaceDesc,
-    IDirectDrawSurface4Impl_Initialize,
-    IDirectDrawSurface4Impl_IsLost,
-    Xlib_IDirectDrawSurface4Impl_Lock,
-    IDirectDrawSurface4Impl_ReleaseDC,
-    IDirectDrawSurface4Impl_Restore,
-    IDirectDrawSurface4Impl_SetClipper,
-    IDirectDrawSurface4Impl_SetColorKey,
-    IDirectDrawSurface4Impl_SetOverlayPosition,
-    Xlib_IDirectDrawSurface4Impl_SetPalette,
-    Xlib_IDirectDrawSurface4Impl_Unlock,
-    Xlib_IDirectDrawSurface4Impl_UpdateOverlay,
-    IDirectDrawSurface4Impl_UpdateOverlayDisplay,
-    IDirectDrawSurface4Impl_UpdateOverlayZOrder,
-    IDirectDrawSurface4Impl_GetDDInterface,
-    IDirectDrawSurface4Impl_PageLock,
-    IDirectDrawSurface4Impl_PageUnlock,
-    IDirectDrawSurface4Impl_SetSurfaceDesc,
-    IDirectDrawSurface4Impl_SetPrivateData,
-    IDirectDrawSurface4Impl_GetPrivateData,
-    IDirectDrawSurface4Impl_FreePrivateData,
-    IDirectDrawSurface4Impl_GetUniquenessValue,
-    IDirectDrawSurface4Impl_ChangeUniquenessValue
-};
diff --git a/dlls/ddraw/helper.c b/dlls/ddraw/helper.c
index b7fc84e..52f984b 100644
--- a/dlls/ddraw/helper.c
+++ b/dlls/ddraw/helper.c
@@ -3,16 +3,12 @@
  *
  * Copyright 1997-1999 Marcus Meissner
  * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
+ * Copyright 2000 TransGaming Technologies Inc.
  */
 
 #include "config.h"
 
-#include <unistd.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include <stddef.h>
 
 #include "winerror.h"
 #include "heap.h"
@@ -27,232 +23,205 @@
 /******************************************************************************
  *		debug output functions
  */
-void _dump_DDBLTFX(DWORD flagmask) {
+typedef struct
+{
+    DWORD val;
+    const char* name;
+} flag_info;
+
+#define FE(x) { x, #x }
+
+typedef struct
+{
+    DWORD val;
+    const char* name;
+    void (*func)(const void *);
+    ptrdiff_t offset;
+} member_info;
+
+#define ME(x,f,e) { x, #x, (void (*)(const void *))(f), offsetof(STRUCT, e) }
+
+static void DDRAW_dump_flags(DWORD flags, const flag_info* names,
+			     size_t num_names)
+{
     int	i;
-    const struct {
-	DWORD	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	FE(DDBLTFX_ARITHSTRETCHY)
-	FE(DDBLTFX_MIRRORLEFTRIGHT)
-	FE(DDBLTFX_MIRRORUPDOWN)
-	FE(DDBLTFX_NOTEARING)
-	FE(DDBLTFX_ROTATE180)
-	FE(DDBLTFX_ROTATE270)
-	FE(DDBLTFX_ROTATE90)
-	FE(DDBLTFX_ZBUFFERRANGE)
-	FE(DDBLTFX_ZBUFFERBASEDEST)
-#undef FE
-    };
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & flagmask)
-	    DPRINTF("%s ",flags[i].name);
+
+    for (i=0; i < num_names; i++)
+	if (names[i].val & flags)
+	    DPRINTF("%s ", names[i].name);
+
     DPRINTF("\n");
 }
 
-void _dump_DDOVERLAY(DWORD flagmask) {
-    int	i;
-    const struct {
-	DWORD	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	FE(DDOVER_ALPHADEST)
-	FE(DDOVER_ALPHADESTCONSTOVERRIDE)
-	FE(DDOVER_ALPHADESTNEG)
-	FE(DDOVER_ALPHADESTSURFACEOVERRIDE)
-	FE(DDOVER_ALPHAEDGEBLEND)
-	FE(DDOVER_ALPHASRC)
-	FE(DDOVER_ALPHASRCCONSTOVERRIDE)
-	FE(DDOVER_ALPHASRCNEG)
-	FE(DDOVER_ALPHASRCSURFACEOVERRIDE)
-	FE(DDOVER_HIDE)
-	FE(DDOVER_KEYDEST)
-	FE(DDOVER_KEYDESTOVERRIDE)
-	FE(DDOVER_KEYSRC)
-	FE(DDOVER_KEYSRCOVERRIDE)
-	FE(DDOVER_SHOW)
-	FE(DDOVER_ADDDIRTYRECT)
-	FE(DDOVER_REFRESHDIRTYRECTS)
-	FE(DDOVER_REFRESHALL)
-	FE(DDOVER_DDFX)
-	FE(DDOVER_AUTOFLIP)
-	FE(DDOVER_BOB)
-	FE(DDOVER_OVERRIDEBOBWEAVE)
-	FE(DDOVER_INTERLEAVED)
-#undef FE
-    };
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & flagmask)
-	    DPRINTF("%s ",flags[i].name);
-    DPRINTF("\n");
+static void DDRAW_dump_members(DWORD flags, const void* data,
+			       const member_info* mems, size_t num_mems)
+{
+    int i;
+
+    for (i=0; i < sizeof(mems)/sizeof(mems[0]); i++)
+    {
+	if (mems[i].val & flags)
+	{
+	    DPRINTF(" - %s : ", mems[i].name);
+	    mems[i].func((const char *)data + mems[i].offset);
+	    DPRINTF("\n");
+	}
+    }
 }
 
-void _dump_DDBLTFAST(DWORD flagmask) {
-    int	i;
-    const struct {
-	DWORD	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	FE(DDBLTFAST_NOCOLORKEY)
-	FE(DDBLTFAST_SRCCOLORKEY)
-	FE(DDBLTFAST_DESTCOLORKEY)
-	FE(DDBLTFAST_WAIT)
-#undef FE
-    };
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & flagmask)
-	    DPRINTF("%s ",flags[i].name);
-    DPRINTF("\n");
+void DDRAW_dump_DDBLTFX(DWORD flagmask)
+{
+    static const flag_info flags[] =
+	{
+	    FE(DDBLTFX_ARITHSTRETCHY),
+	    FE(DDBLTFX_MIRRORLEFTRIGHT),
+	    FE(DDBLTFX_MIRRORUPDOWN),
+	    FE(DDBLTFX_NOTEARING),
+	    FE(DDBLTFX_ROTATE180),
+	    FE(DDBLTFX_ROTATE270),
+	    FE(DDBLTFX_ROTATE90),
+	    FE(DDBLTFX_ZBUFFERRANGE),
+	    FE(DDBLTFX_ZBUFFERBASEDEST)
+	};
+
+    DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
 }
 
-void _dump_DDBLT(DWORD flagmask) {
-    int	i;
-    const struct {
-	DWORD	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	FE(DDBLT_ALPHADEST)
-	FE(DDBLT_ALPHADESTCONSTOVERRIDE)
-	FE(DDBLT_ALPHADESTNEG)
-	FE(DDBLT_ALPHADESTSURFACEOVERRIDE)
-	FE(DDBLT_ALPHAEDGEBLEND)
-	FE(DDBLT_ALPHASRC)
-	FE(DDBLT_ALPHASRCCONSTOVERRIDE)
-	FE(DDBLT_ALPHASRCNEG)
-	FE(DDBLT_ALPHASRCSURFACEOVERRIDE)
-	FE(DDBLT_ASYNC)
-	FE(DDBLT_COLORFILL)
-	FE(DDBLT_DDFX)
-	FE(DDBLT_DDROPS)
-	FE(DDBLT_KEYDEST)
-	FE(DDBLT_KEYDESTOVERRIDE)
-	FE(DDBLT_KEYSRC)
-	FE(DDBLT_KEYSRCOVERRIDE)
-	FE(DDBLT_ROP)
-	FE(DDBLT_ROTATIONANGLE)
-	FE(DDBLT_ZBUFFER)
-	FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE)
-	FE(DDBLT_ZBUFFERDESTOVERRIDE)
-	FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE)
-	FE(DDBLT_ZBUFFERSRCOVERRIDE)
-	FE(DDBLT_WAIT)
-	FE(DDBLT_DEPTHFILL)
-#undef FE
-    };
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & flagmask)
-	    DPRINTF("%s ",flags[i].name);
-    DPRINTF("\n");
+void DDRAW_dump_DDBLTFAST(DWORD flagmask)
+{
+    static const flag_info flags[] =
+	{
+	    FE(DDBLTFAST_NOCOLORKEY),
+	    FE(DDBLTFAST_SRCCOLORKEY),
+	    FE(DDBLTFAST_DESTCOLORKEY),
+	    FE(DDBLTFAST_WAIT)
+	};
+
+    DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
 }
 
-void _dump_DDSCAPS(void *in) {
-    int	i;
-    const struct {
-	DWORD	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	FE(DDSCAPS_RESERVED1)
-	FE(DDSCAPS_ALPHA)
-	FE(DDSCAPS_BACKBUFFER)
-	FE(DDSCAPS_COMPLEX)
-	FE(DDSCAPS_FLIP)
-	FE(DDSCAPS_FRONTBUFFER)
-	FE(DDSCAPS_OFFSCREENPLAIN)
-	FE(DDSCAPS_OVERLAY)
-	FE(DDSCAPS_PALETTE)
-	FE(DDSCAPS_PRIMARYSURFACE)
-	FE(DDSCAPS_PRIMARYSURFACELEFT)
-	FE(DDSCAPS_SYSTEMMEMORY)
-	FE(DDSCAPS_TEXTURE)
-	FE(DDSCAPS_3DDEVICE)
-	FE(DDSCAPS_VIDEOMEMORY)
-	FE(DDSCAPS_VISIBLE)
-	FE(DDSCAPS_WRITEONLY)
-	FE(DDSCAPS_ZBUFFER)
-	FE(DDSCAPS_OWNDC)
-	FE(DDSCAPS_LIVEVIDEO)
-	FE(DDSCAPS_HWCODEC)
-	FE(DDSCAPS_MODEX)
-	FE(DDSCAPS_MIPMAP)
-	FE(DDSCAPS_RESERVED2)
-	FE(DDSCAPS_ALLOCONLOAD)
-	FE(DDSCAPS_VIDEOPORT)
-	FE(DDSCAPS_LOCALVIDMEM)
-	FE(DDSCAPS_NONLOCALVIDMEM)
-	FE(DDSCAPS_STANDARDVGAMODE)
-	FE(DDSCAPS_OPTIMIZED)
-#undef FE
+void DDRAW_dump_DDBLT(DWORD flagmask)
+{
+    static const flag_info flags[] =
+	{
+	    FE(DDBLT_ALPHADEST),
+	    FE(DDBLT_ALPHADESTCONSTOVERRIDE),
+	    FE(DDBLT_ALPHADESTNEG),
+	    FE(DDBLT_ALPHADESTSURFACEOVERRIDE),
+	    FE(DDBLT_ALPHAEDGEBLEND),
+	    FE(DDBLT_ALPHASRC),
+	    FE(DDBLT_ALPHASRCCONSTOVERRIDE),
+	    FE(DDBLT_ALPHASRCNEG),
+	    FE(DDBLT_ALPHASRCSURFACEOVERRIDE),
+	    FE(DDBLT_ASYNC),
+	    FE(DDBLT_COLORFILL),
+	    FE(DDBLT_DDFX),
+	    FE(DDBLT_DDROPS),
+	    FE(DDBLT_KEYDEST),
+	    FE(DDBLT_KEYDESTOVERRIDE),
+	    FE(DDBLT_KEYSRC),
+	    FE(DDBLT_KEYSRCOVERRIDE),
+	    FE(DDBLT_ROP),
+	    FE(DDBLT_ROTATIONANGLE),
+	    FE(DDBLT_ZBUFFER),
+	    FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE),
+	    FE(DDBLT_ZBUFFERDESTOVERRIDE),
+	    FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE),
+	    FE(DDBLT_ZBUFFERSRCOVERRIDE),
+	    FE(DDBLT_WAIT),
+	    FE(DDBLT_DEPTHFILL)
     };
-    DWORD flagmask = *((DWORD *) in);
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & flagmask)
-	    DPRINTF("%s ",flags[i].name);
+
+    DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
 }
 
-void _dump_pixelformat_flag(DWORD flagmask) {
-    int	i;
-    const struct {
-	DWORD	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	FE(DDPF_ALPHAPIXELS)
-	FE(DDPF_ALPHA)
-	FE(DDPF_FOURCC)
-	FE(DDPF_PALETTEINDEXED4)
-	FE(DDPF_PALETTEINDEXEDTO8)
-	FE(DDPF_PALETTEINDEXED8)
-	FE(DDPF_RGB)
-	FE(DDPF_COMPRESSED)
-	FE(DDPF_RGBTOYUV)
-	FE(DDPF_YUV)
-	FE(DDPF_ZBUFFER)
-	FE(DDPF_PALETTEINDEXED1)
-	FE(DDPF_PALETTEINDEXED2)
-	FE(DDPF_ZPIXELS)
-#undef FE
+void DDRAW_dump_DDSCAPS(const DDSCAPS2 *in)
+{
+    static const flag_info flags[] = 
+	{
+	    FE(DDSCAPS_RESERVED1),
+	    FE(DDSCAPS_ALPHA),
+	    FE(DDSCAPS_BACKBUFFER),
+	    FE(DDSCAPS_COMPLEX),
+	    FE(DDSCAPS_FLIP),
+	    FE(DDSCAPS_FRONTBUFFER),
+	    FE(DDSCAPS_OFFSCREENPLAIN),
+	    FE(DDSCAPS_OVERLAY),
+	    FE(DDSCAPS_PALETTE),
+	    FE(DDSCAPS_PRIMARYSURFACE),
+	    FE(DDSCAPS_PRIMARYSURFACELEFT),
+	    FE(DDSCAPS_SYSTEMMEMORY),
+	    FE(DDSCAPS_TEXTURE),
+	    FE(DDSCAPS_3DDEVICE),
+	    FE(DDSCAPS_VIDEOMEMORY),
+	    FE(DDSCAPS_VISIBLE),
+	    FE(DDSCAPS_WRITEONLY),
+	    FE(DDSCAPS_ZBUFFER),
+	    FE(DDSCAPS_OWNDC),
+	    FE(DDSCAPS_LIVEVIDEO),
+	    FE(DDSCAPS_HWCODEC),
+	    FE(DDSCAPS_MODEX),
+	    FE(DDSCAPS_MIPMAP),
+	    FE(DDSCAPS_RESERVED2),
+	    FE(DDSCAPS_ALLOCONLOAD),
+	    FE(DDSCAPS_VIDEOPORT),
+	    FE(DDSCAPS_LOCALVIDMEM),
+	    FE(DDSCAPS_NONLOCALVIDMEM),
+	    FE(DDSCAPS_STANDARDVGAMODE),
+	    FE(DDSCAPS_OPTIMIZED)
     };
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & flagmask)
-	    DPRINTF("%s ",flags[i].name);
+
+    DDRAW_dump_flags(in->dwCaps, flags, sizeof(flags)/sizeof(flags[0]));
 }
 
-void _dump_paletteformat(DWORD dwFlags) {
-    int	i;
-    const struct {
-	DWORD	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	FE(DDPCAPS_4BIT)
-	FE(DDPCAPS_8BITENTRIES)
-	FE(DDPCAPS_8BIT)
-	FE(DDPCAPS_INITIALIZE)
-	FE(DDPCAPS_PRIMARYSURFACE)
-	FE(DDPCAPS_PRIMARYSURFACELEFT)
-	FE(DDPCAPS_ALLOW256)
-	FE(DDPCAPS_VSYNC)
-	FE(DDPCAPS_1BIT)
-	FE(DDPCAPS_2BIT)
-	FE(DDPCAPS_ALPHA)
-#undef FE
+void DDRAW_dump_pixelformat_flag(DWORD flagmask)
+{
+    static const flag_info flags[] =
+	{
+	    FE(DDPF_ALPHAPIXELS),
+	    FE(DDPF_ALPHA),
+	    FE(DDPF_FOURCC),
+	    FE(DDPF_PALETTEINDEXED4),
+	    FE(DDPF_PALETTEINDEXEDTO8),
+	    FE(DDPF_PALETTEINDEXED8),
+	    FE(DDPF_RGB),
+	    FE(DDPF_COMPRESSED),
+	    FE(DDPF_RGBTOYUV),
+	    FE(DDPF_YUV),
+	    FE(DDPF_ZBUFFER),
+	    FE(DDPF_PALETTEINDEXED1),
+	    FE(DDPF_PALETTEINDEXED2),
+	    FE(DDPF_ZPIXELS)
     };
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & dwFlags)
-	    DPRINTF("%s ",flags[i].name);
-    DPRINTF("\n");
+
+    DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
 }
 
-void _dump_pixelformat(void *in) {
+void DDRAW_dump_paletteformat(DWORD dwFlags)
+{
+    static const flag_info flags[] =
+	{
+	    FE(DDPCAPS_4BIT),
+	    FE(DDPCAPS_8BITENTRIES),
+	    FE(DDPCAPS_8BIT),
+	    FE(DDPCAPS_INITIALIZE),
+	    FE(DDPCAPS_PRIMARYSURFACE),
+	    FE(DDPCAPS_PRIMARYSURFACELEFT),
+	    FE(DDPCAPS_ALLOW256),
+	    FE(DDPCAPS_VSYNC),
+	    FE(DDPCAPS_1BIT),
+	    FE(DDPCAPS_2BIT),
+	    FE(DDPCAPS_ALPHA)
+    };
+
+    DDRAW_dump_flags(dwFlags, flags, sizeof(flags)/sizeof(flags[0]));
+}
+
+void DDRAW_dump_pixelformat(void *in) {
     LPDDPIXELFORMAT pf = (LPDDPIXELFORMAT) in;
 
     DPRINTF("( ");
-    _dump_pixelformat_flag(pf->dwFlags);
+    DDRAW_dump_pixelformat_flag(pf->dwFlags);
     if (pf->dwFlags & DDPF_FOURCC) {
 	DPRINTF(", dwFourCC code '%c%c%c%c' (0x%08lx) - %ld bits per pixel",
 		(unsigned char)( pf->dwFourCC     &0xff),
@@ -260,13 +229,13 @@
 		(unsigned char)((pf->dwFourCC>>16)&0xff),
 		(unsigned char)((pf->dwFourCC>>24)&0xff),
 		pf->dwFourCC,
-		pf->u.dwYUVBitCount
+		pf->u1.dwYUVBitCount
 	);
     }
     if (pf->dwFlags & DDPF_RGB) {
 	char *cmd;
-	DPRINTF(", RGB bits: %ld, ", pf->u.dwRGBBitCount);
-	switch (pf->u.dwRGBBitCount) {
+	DPRINTF(", RGB bits: %ld, ", pf->u1.dwRGBBitCount);
+	switch (pf->u1.dwRGBBitCount) {
 	case 4: cmd = "%1lx"; break;
 	case 8: cmd = "%02lx"; break;
 	case 16: cmd = "%04lx"; break;
@@ -274,114 +243,95 @@
 	case 32: cmd = "%08lx"; break;
 	default: ERR("Unexpected bit depth !\n"); cmd = "%d"; break;
 	}
-	DPRINTF(" R "); DPRINTF(cmd, pf->u1.dwRBitMask);
-	DPRINTF(" G "); DPRINTF(cmd, pf->u2.dwGBitMask);
-	DPRINTF(" B "); DPRINTF(cmd, pf->u3.dwBBitMask);
+	DPRINTF(" R "); DPRINTF(cmd, pf->u2.dwRBitMask);
+	DPRINTF(" G "); DPRINTF(cmd, pf->u3.dwGBitMask);
+	DPRINTF(" B "); DPRINTF(cmd, pf->u4.dwBBitMask);
 	if (pf->dwFlags & DDPF_ALPHAPIXELS) {
-	    DPRINTF(" A "); DPRINTF(cmd, pf->u4.dwRGBAlphaBitMask);
+	    DPRINTF(" A "); DPRINTF(cmd, pf->u5.dwRGBAlphaBitMask);
 	}
 	if (pf->dwFlags & DDPF_ZPIXELS) {
-	    DPRINTF(" Z "); DPRINTF(cmd, pf->u4.dwRGBZBitMask);
+	    DPRINTF(" Z "); DPRINTF(cmd, pf->u5.dwRGBZBitMask);
 	}
     }
     if (pf->dwFlags & DDPF_ZBUFFER) {
-	DPRINTF(", Z bits : %ld", pf->u.dwZBufferBitDepth);
+	DPRINTF(", Z bits : %ld", pf->u1.dwZBufferBitDepth);
     }
     if (pf->dwFlags & DDPF_ALPHA) {
-	DPRINTF(", Alpha bits : %ld", pf->u.dwAlphaBitDepth);
+	DPRINTF(", Alpha bits : %ld", pf->u1.dwAlphaBitDepth);
     }
     DPRINTF(")");
 }
 
-void _dump_colorkeyflag(DWORD ck) {
-    int	i;
-    const struct {
-	DWORD	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	FE(DDCKEY_COLORSPACE)
-	FE(DDCKEY_DESTBLT)
-	FE(DDCKEY_DESTOVERLAY)
-	FE(DDCKEY_SRCBLT)
-	FE(DDCKEY_SRCOVERLAY)
-#undef FE
+void DDRAW_dump_colorkeyflag(DWORD ck)
+{
+    static const flag_info flags[] =
+	{
+	    FE(DDCKEY_COLORSPACE),
+	    FE(DDCKEY_DESTBLT),
+	    FE(DDCKEY_DESTOVERLAY),
+	    FE(DDCKEY_SRCBLT),
+	    FE(DDCKEY_SRCOVERLAY)
     };
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & ck)
-	    DPRINTF("%s ",flags[i].name);
+
+    DDRAW_dump_flags(ck, flags, sizeof(flags)/sizeof(flags[0]));
 }
 
-static void _dump_DWORD(void *in) {
-    DPRINTF("%ld", *((DWORD *) in));
+static void DDRAW_dump_DWORD(const void *in) {
+    DPRINTF("%ld", *((const DWORD *) in));
 }
-static void _dump_PTR(void *in) {
-    DPRINTF("%p", *((void **) in));
+static void DDRAW_dump_PTR(const void *in) {
+    DPRINTF("%p", *((const void **) in));
 }
-void _dump_DDCOLORKEY(void *in) {
-    DDCOLORKEY *ddck = (DDCOLORKEY *) in;
+void DDRAW_dump_DDCOLORKEY(const void *in) {
+    const DDCOLORKEY *ddck = (const DDCOLORKEY *) in;
 
     DPRINTF(" Low : %ld  - High : %ld", ddck->dwColorSpaceLowValue, ddck->dwColorSpaceHighValue);
 }
 
-void _dump_surface_desc(DDSURFACEDESC *lpddsd) {
-    int	i;
-    struct {
-	DWORD	mask;
-	char	*name;
-	void (*func)(void *);
-	void	*elt;
-    } flags[16], *fe = flags;
-#define FE(x,f,e) do { fe->mask = x;  fe->name = #x; fe->func = f; fe->elt = (void *) &(lpddsd->e); fe++; } while(0)
-	FE(DDSD_CAPS, _dump_DDSCAPS, ddsCaps);
-	FE(DDSD_HEIGHT, _dump_DWORD, dwHeight);
-	FE(DDSD_WIDTH, _dump_DWORD, dwWidth);
-	FE(DDSD_PITCH, _dump_DWORD, lPitch);
-	FE(DDSD_BACKBUFFERCOUNT, _dump_DWORD, dwBackBufferCount);
-	FE(DDSD_ZBUFFERBITDEPTH, _dump_DWORD, u.dwZBufferBitDepth);
-	FE(DDSD_ALPHABITDEPTH, _dump_DWORD, dwAlphaBitDepth);
-	FE(DDSD_PIXELFORMAT, _dump_pixelformat, ddpfPixelFormat);
-	FE(DDSD_CKDESTOVERLAY, _dump_DDCOLORKEY, ddckCKDestOverlay);
-	FE(DDSD_CKDESTBLT, _dump_DDCOLORKEY, ddckCKDestBlt);
-	FE(DDSD_CKSRCOVERLAY, _dump_DDCOLORKEY, ddckCKSrcOverlay);
-	FE(DDSD_CKSRCBLT, _dump_DDCOLORKEY, ddckCKSrcBlt);
-	FE(DDSD_MIPMAPCOUNT, _dump_DWORD, u.dwMipMapCount);
-	FE(DDSD_REFRESHRATE, _dump_DWORD, u.dwRefreshRate);
-	FE(DDSD_LINEARSIZE, _dump_DWORD, u1.dwLinearSize);
-	FE(DDSD_LPSURFACE, _dump_PTR, u1.lpSurface);
-#undef FE
+void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd)
+{
+#define STRUCT DDSURFACEDESC2
+    static const member_info members[] =
+	{
+	    ME(DDSD_CAPS, DDRAW_dump_DDSCAPS, ddsCaps),
+	    ME(DDSD_HEIGHT, DDRAW_dump_DWORD, dwHeight),
+	    ME(DDSD_WIDTH, DDRAW_dump_DWORD, dwWidth),
+	    ME(DDSD_PITCH, DDRAW_dump_DWORD, u1.lPitch),
+	    ME(DDSD_LINEARSIZE, DDRAW_dump_DWORD, u1.dwLinearSize),
+	    ME(DDSD_BACKBUFFERCOUNT, DDRAW_dump_DWORD, dwBackBufferCount),
+	    ME(DDSD_MIPMAPCOUNT, DDRAW_dump_DWORD, u2.dwMipMapCount),
+	    ME(DDSD_REFRESHRATE, DDRAW_dump_DWORD, u2.dwRefreshRate),
+	    ME(DDSD_ALPHABITDEPTH, DDRAW_dump_DWORD, dwAlphaBitDepth),
+	    ME(DDSD_LPSURFACE, DDRAW_dump_PTR, lpSurface),
+	    ME(DDSD_CKDESTOVERLAY, DDRAW_dump_DDCOLORKEY, u3.ddckCKDestOverlay),
+	    ME(DDSD_CKDESTBLT, DDRAW_dump_DDCOLORKEY, ddckCKDestBlt),
+	    ME(DDSD_CKSRCOVERLAY, DDRAW_dump_DDCOLORKEY, ddckCKSrcOverlay),
+	    ME(DDSD_CKSRCBLT, DDRAW_dump_DDCOLORKEY, ddckCKSrcBlt),
+	    ME(DDSD_PIXELFORMAT, DDRAW_dump_pixelformat, u4.ddpfPixelFormat)
+	};
 
-    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	if (flags[i].mask & lpddsd->dwFlags) {
-	    DPRINTF(" - %s : ",flags[i].name);
-	    flags[i].func(flags[i].elt);
-	    DPRINTF("\n");  
-	}
+    DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members,
+		       sizeof(members)/sizeof(members[0]));
 }
-void _dump_cooperativelevel(DWORD cooplevel) {
-    int i;
-    const struct {
-	int	mask;
-	char	*name;
-    } flags[] = {
-#define FE(x) { x, #x},
-	    FE(DDSCL_FULLSCREEN)
-	    FE(DDSCL_ALLOWREBOOT)
-	    FE(DDSCL_NOWINDOWCHANGES)
-	    FE(DDSCL_NORMAL)
-	    FE(DDSCL_ALLOWMODEX)
-	    FE(DDSCL_EXCLUSIVE)
-	    FE(DDSCL_SETFOCUSWINDOW)
-	    FE(DDSCL_SETDEVICEWINDOW)
+
+void DDRAW_dump_cooperativelevel(DWORD cooplevel)
+{
+    static const flag_info flags[] =
+	{
+	    FE(DDSCL_FULLSCREEN),
+	    FE(DDSCL_ALLOWREBOOT),
+	    FE(DDSCL_NOWINDOWCHANGES),
+	    FE(DDSCL_NORMAL),
+	    FE(DDSCL_ALLOWMODEX),
+	    FE(DDSCL_EXCLUSIVE),
+	    FE(DDSCL_SETFOCUSWINDOW),
+	    FE(DDSCL_SETDEVICEWINDOW),
 	    FE(DDSCL_CREATEDEVICEWINDOW)
-#undef FE
     };
 
-    if (TRACE_ON(ddraw)) {
+    if (TRACE_ON(ddraw))
+    {
 	DPRINTF(" - ");
-	for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-	    if (flags[i].mask & cooplevel)
-		DPRINTF("%s ",flags[i].name);
-	DPRINTF("\n");
+	DDRAW_dump_flags(cooplevel, flags, sizeof(flags)/sizeof(flags[0]));
     }
 }
diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c
index 30722e5..3c4acf6 100644
--- a/dlls/ddraw/main.c
+++ b/dlls/ddraw/main.c
@@ -2,41 +2,36 @@
  *
  * Copyright 1997-1999 Marcus Meissner
  * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
+ * Copyright 2000 TransGaming Technologies Inc.
+ *
+ * This file contains the (internal) driver registration functions,
+ * driver enumeration APIs and DirectDraw creation functions.
  */
 
 #include "config.h"
 
-#include <unistd.h>
 #include <assert.h>
-#include <fcntl.h>
 #include <string.h>
 #include <stdlib.h>
-#include <stdio.h>
 
 #include "winerror.h"
-#include "heap.h"
-#include "wine/exception.h"
 #include "debugtools.h"
+#include "heap.h"
+
+#include "initguid.h"
+#include "ddraw.h"
+#include "d3d.h"
 
 /* This for all the enumeration and creation of D3D-related objects */
 #include "ddraw_private.h"
 
-#define MAX_DDRAW_DRIVERS	3
-static ddraw_driver * ddraw_drivers[MAX_DDRAW_DRIVERS];
-static int nrof_ddraw_drivers			= 0;
+#define MAX_DDRAW_DRIVERS 3
+static const ddraw_driver* DDRAW_drivers[MAX_DDRAW_DRIVERS];
+static int DDRAW_num_drivers; /* = 0 */
+static int DDRAW_default_driver;
 
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
-/* register a direct draw driver. We better not use malloc for we are in 
- * the ELF startup initialisation at this point.
- */
-void ddraw_register_driver(ddraw_driver *driver) {
-    ddraw_drivers[nrof_ddraw_drivers++] = driver;
-
-    /* increase MAX_DDRAW_DRIVERS if the line below triggers */
-    assert(nrof_ddraw_drivers <= MAX_DDRAW_DRIVERS);
-}
-
 /**********************************************************************/
 
 typedef struct {
@@ -51,7 +46,6 @@
     LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags)
 {
     int i;
-    GUID	zeroGUID;
     TRACE("(%p,%p, %08lx)\n", lpCallback, lpContext, dwFlags);
 
     if (TRACE_ON(ddraw)) {
@@ -64,43 +58,20 @@
 	    DPRINTF("DDENUM_NONDISPLAYDEVICES ");
 	DPRINTF("\n");
     }
-    if (dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES) {
-	FIXME("no attached secondary devices supported.\n");
-	/*return E_FAIL;*/
-    }
 
-    memset(&zeroGUID,0,sizeof(zeroGUID));
+    for (i=0; i<DDRAW_num_drivers; i++)
+    {
+        TRACE("Enumerating %s/%s interface\n",
+	      DDRAW_drivers[i]->info->szDriver,
+	      DDRAW_drivers[i]->info->szDescription);
 
-    /* we have at least one DDRAW driver */
-    if (ddraw_drivers[0]) {
-	if (!lpCallback(
-	    &zeroGUID, /* FIXME: or NULL? -MM */
-	    "WINE DirectDraw",
-	    "display",
-	    lpContext,
-	    0		/* FIXME: flags not supported here */
-	))
-	    return DD_OK;
-    }
-    /* Invoke callback for what flags we do support */
-    for (i=0;i<MAX_DDRAW_DRIVERS;i++) {
-	if (!ddraw_drivers[i])
-	    continue;
-	if (ddraw_drivers[i]->createDDRAW(NULL)) /* !0 is failing */
-	    continue;
-        TRACE("Enumerating %s/%s interface\n",ddraw_drivers[i]->name,ddraw_drivers[i]->type);
-	if (!lpCallback(
-	    ddraw_drivers[i]->guid,
-	    (LPSTR)ddraw_drivers[i]->name,
-	    (LPSTR)ddraw_drivers[i]->type,
-	    lpContext,
-	    0		/* FIXME: flags not supported here */
-	))
-	    return DD_OK;
-    }
-    if (nrof_ddraw_drivers) {
-	TRACE("Enumerating the default interface\n");
-	if (!lpCallback(NULL,"WINE (default)", "display", lpContext, 0))
+	/* We have to pass NULL from the primary display device.
+	 * RoadRage chapter 6's enumeration routine expects it. */
+	if (!lpCallback((DDRAW_default_driver == i) ? NULL
+			:(LPGUID)&DDRAW_drivers[i]->info->guidDeviceIdentifier,
+			(LPSTR)DDRAW_drivers[i]->info->szDescription,
+			(LPSTR)DDRAW_drivers[i]->info->szDriver,
+			lpContext, 0))
 	    return DD_OK;
     }
 
@@ -137,8 +108,6 @@
     return bResult;
 }
 
-/**********************************************************************/
-
 HRESULT WINAPI DirectDrawEnumerateExW(
   LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags)
 {
@@ -163,8 +132,6 @@
 	lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext);
 }
 
-/**********************************************************************/
-
 HRESULT WINAPI DirectDrawEnumerateA(
   LPDDENUMCALLBACKA lpCallback, LPVOID lpContext) 
 {
@@ -189,8 +156,6 @@
 	lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext);
 }
 
-/**********************************************************************/
-
 HRESULT WINAPI DirectDrawEnumerateW(
   LPDDENUMCALLBACKW lpCallback, LPVOID lpContext) 
 {
@@ -201,215 +166,203 @@
     return DirectDrawEnumerateExW(DirectDrawEnumerateProcW, (LPVOID) &epd, 0);
 }
 
-/******************************************************************************
- * 				DirectDraw Window Procedure
+/***********************************************************************
+ *		DirectDrawCreate
  */
-static LRESULT WINAPI DDWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+
+const ddraw_driver* DDRAW_FindDriver(const GUID* pGUID)
 {
-    LRESULT ret;
-    IDirectDrawImpl* ddraw = NULL;
-    DWORD lastError;
+    static const GUID zeroGUID; /* gets zero-inited */
 
-    /* FIXME(ddraw,"(0x%04x,%s,0x%08lx,0x%08lx),stub!\n",(int)hwnd,SPY_GetMsgName(msg),(long)wParam,(long)lParam); */
+    TRACE("(%s)\n", pGUID ? debugstr_guid(pGUID) : "(null)");
 
-    SetLastError( ERROR_SUCCESS );
-    ddraw  = (IDirectDrawImpl*)GetPropA( hwnd, ddProp );
-    if( (!ddraw)  && ( ( lastError = GetLastError() ) != ERROR_SUCCESS )) 
-	ERR("Unable to retrieve this ptr from window. Error %08lx\n",lastError);
+    if (DDRAW_num_drivers == 0) return NULL;
 
-    if( ddraw ) {
-    /* Perform any special direct draw functions */
-	if (msg==WM_PAINT)
-	    ddraw->d->paintable = 1;
+    if (pGUID == (LPGUID)DDCREATE_EMULATIONONLY
+	|| pGUID == (LPGUID)DDCREATE_HARDWAREONLY)
+	pGUID = NULL;
 
-	/* Now let the application deal with the rest of this */
-	if( ddraw->d->mainWindow ) {
+    if (pGUID == NULL || memcmp(pGUID, &zeroGUID, sizeof(GUID)) == 0)
+    {
+	/* Use the default driver. */
+	return DDRAW_drivers[DDRAW_default_driver];
+    }
+    else
+    {
+	/* Look for a matching GUID. */
 
-	    /* Don't think that we actually need to call this but... 
-	     * might as well be on the safe side of things...
-	     */
+	int i;
+	for (i=0; i < DDRAW_num_drivers; i++)
+	{
+	    if (IsEqualGUID(pGUID,
+			    &DDRAW_drivers[i]->info->guidDeviceIdentifier))
+		break;
+	}
 
-	    /* I changed hwnd to ddraw->d->mainWindow as I did not see why
-	     * it should be the procedures of our fake window that gets called
-	     * instead of those of the window provided by the application.
-	     * And with this patch, mouse clicks work with Monkey Island III
-	     * - Lionel
-	     */
-	    ret = DefWindowProcA( ddraw->d->mainWindow, msg, wParam, lParam );
+	if (i < DDRAW_num_drivers)
+	{
+	    return DDRAW_drivers[i];
+	}
+	else
+	{
+	    ERR("(%s): did not recognize requested GUID.\n",debugstr_guid(pGUID));
+	    return NULL;
+	}
+    }
+}
 
-	    if( !ret ) {
-		/* We didn't handle the message - give it to the application */
-		if (ddraw && ddraw->d->mainWindow)
-                {
-                    WNDPROC winproc = (WNDPROC)GetWindowLongA( ddraw->d->mainWindow, GWL_WNDPROC );
-		    ret = CallWindowProcA(winproc, ddraw->d->mainWindow, msg, wParam, lParam );
-                }
-	    }
-	    return ret;
-	} /* else FALLTHROUGH */
-    } /* else FALLTHROUGH */
-    return DefWindowProcA(hwnd,msg,wParam,lParam);
+static HRESULT DDRAW_Create(
+	LPGUID lpGUID, LPVOID *lplpDD, LPUNKNOWN pUnkOuter, REFIID iid, BOOL ex
+) {
+    const ddraw_driver* driver;
+    LPDIRECTDRAW7 pDD;
+    HRESULT hr;
+
+    if (DDRAW_num_drivers == 0)
+    {
+	WARN("no DirectDraw drivers registered\n");
+	return DDERR_INVALIDDIRECTDRAWGUID;
+    }
+
+    if (lpGUID == (LPGUID)DDCREATE_EMULATIONONLY
+	|| lpGUID == (LPGUID)DDCREATE_HARDWAREONLY)
+	lpGUID = NULL;
+
+    TRACE("(%s,%p,%p)\n",debugstr_guid(lpGUID),lplpDD,pUnkOuter);
+
+    if (pUnkOuter != NULL)
+	return DDERR_INVALIDPARAMS; /* CLASS_E_NOAGGREGATION? */
+
+    driver = DDRAW_FindDriver(lpGUID);
+    if (driver == NULL) return DDERR_INVALIDDIRECTDRAWGUID;
+
+    hr = driver->create(lpGUID, &pDD, pUnkOuter, ex);
+    if (FAILED(hr)) return hr;
+
+    hr = IDirectDraw7_QueryInterface(pDD, iid, lplpDD);
+    IDirectDraw7_Release(pDD);
+    return hr;
 }
 
 /***********************************************************************
  *		DirectDrawCreate
+ *
+ * Only creates legacy IDirectDraw interfaces.
+ * Cannot create IDirectDraw7 interfaces.
+ * In theory.
  */
 HRESULT WINAPI DirectDrawCreate(
-	LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter
+	LPGUID lpGUID, LPDIRECTDRAW* lplpDD, LPUNKNOWN pUnkOuter
 ) {
-    IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
-    WNDCLASSA	wc;
-    HRESULT	ret = 0;
-    int		i,drvindex=0;
-    GUID	zeroGUID;
-
-    struct ddraw_driver	*ddd = NULL;
-
-    if (!HIWORD(lpGUID)) lpGUID = NULL;
-
-    TRACE("(%s,%p,%p)\n",debugstr_guid(lpGUID),ilplpDD,pUnkOuter);
-
-    memset(&zeroGUID,0,sizeof(zeroGUID));
-    while (1) {
-	ddd = NULL;
-	if ( ( !lpGUID ) ||
-	     ( IsEqualGUID( &zeroGUID,  lpGUID ) ) ||
-	     ( IsEqualGUID( &IID_IDirectDraw,  lpGUID ) ) ||
-	     ( IsEqualGUID( &IID_IDirectDraw2, lpGUID ) ) ||
-	     ( IsEqualGUID( &IID_IDirectDraw4, lpGUID ) ) ||
-	     ( IsEqualGUID( &IID_IDirectDraw7, lpGUID ) )
-	) {
-	    /* choose an interface out of the list */
-	    for (i=0;i<nrof_ddraw_drivers;i++) {
-		ddraw_driver *xddd = ddraw_drivers[i];
-		if (!xddd)
-		    continue;
-		if (!ddd || (ddd->preference<xddd->preference)) {
-		    drvindex = i;
-		    ddd = xddd;
-		}
-	    }
-	} else {
-	    for (i=0;i<nrof_ddraw_drivers;i++) {
-		if (!ddraw_drivers[i])
-		    continue;
-		if (IsEqualGUID(ddraw_drivers[i]->guid,lpGUID)) {
-		    drvindex = i;
-		    ddd = ddraw_drivers[i];
-		    break;
-		}
-	    }
-	}
-	if (!ddd) {
-	    if (!nrof_ddraw_drivers) {
-		ERR("DirectDrawCreate(%s,%p,%p): no DirectDraw drivers compiled in.\n",debugstr_guid(lpGUID),lplpDD,pUnkOuter);
-		return DDERR_NODIRECTDRAWHW;
-	    }
-	    ERR("DirectDrawCreate(%s,%p,%p): did not recognize requested GUID.\n",debugstr_guid(lpGUID),lplpDD,pUnkOuter);
-	    return DDERR_INVALIDDIRECTDRAWGUID;
-	}
-	TRACE("using \"%s\" driver, calling %p\n",ddd->name,ddd->createDDRAW);
-
-	ret = ddd->createDDRAW(lplpDD);
-	if (!ret)
-	    break;
-	ddraw_drivers[drvindex] = NULL; /* mark this one as unusable */
-    }
-
-    if (lpGUID &&
-	(IsEqualGUID( &IID_IDirectDraw2, lpGUID ) ||
-	 IsEqualGUID( &IID_IDirectDraw4, lpGUID ) ||
-	 IsEqualGUID( &IID_IDirectDraw7, lpGUID )
-	)
-    ) {
-	LPVOID x;
-	ret = IDirectDraw_QueryInterface(*lplpDD,lpGUID,&x);
-	IDirectDraw_Release(*lplpDD); /* either drop 1 refcount, or release */
-	if (!ret)
-	    *lplpDD = x;
-	else
-	    return ret;
-    }
-    wc.style		= CS_GLOBALCLASS;
-    wc.lpfnWndProc	= DDWndProc;
-    wc.cbClsExtra	= 0;
-    wc.cbWndExtra	= 0;
-
-    /* We can be a child of the desktop since we're really important */
-    wc.hInstance= 0; 
-    wc.hIcon	= 0;
-    wc.hCursor	= (HCURSOR)IDC_ARROWA;
-    wc.hbrBackground	= NULL_BRUSH;
-    wc.lpszMenuName 	= 0;
-    wc.lpszClassName	= "WINE_DirectDraw";
-    (*ilplpDD)->d->winclass = RegisterClassA(&wc);
-    return ret;
+  return DDRAW_Create(lpGUID,(LPVOID*)lplpDD,pUnkOuter,&IID_IDirectDraw,FALSE);
 }
 
 /***********************************************************************
  *		DirectDrawCreateEx
+ *
+ * Only creates new IDirectDraw7 interfaces.
+ * Supposed to fail if legacy interfaces are requested.
+ * In theory.
  */
 HRESULT WINAPI DirectDrawCreateEx(
 	LPGUID lpGUID, LPVOID* lplpDD, REFIID iid, LPUNKNOWN pUnkOuter
 ) {
-  LPDIRECTDRAW	ddraw;
-  HRESULT	hres;
+    if (!IsEqualGUID(iid, &IID_IDirectDraw7))
+	return DDERR_INVALIDPARAMS;
 
-  FIXME("(%p,%p,%s,%p), might be wrong.\n",lpGUID,lplpDD,debugstr_guid(iid),pUnkOuter);
-
-  hres=DirectDrawCreate(lpGUID,(LPDIRECTDRAW*)&ddraw,pUnkOuter);
-  if (!hres) {
-      hres=IDirectDraw_QueryInterface(ddraw,iid,lplpDD);
-      IDirectDraw_Release(ddraw);
-  }
-  return hres;
+  return DDRAW_Create(lpGUID, lplpDD, pUnkOuter, iid, TRUE);
 }
 
-/*******************************************************************************
+extern HRESULT Uninit_DirectDraw_Create(const GUID*, LPDIRECTDRAW7*,
+					LPUNKNOWN, BOOL);
+
+/* This is for the class factory. */
+static HRESULT DDRAW_CreateDirectDraw(IUnknown* pUnkOuter, REFIID iid,
+				      LPVOID* ppObj)
+{
+    LPDIRECTDRAW7 pDD;
+    HRESULT hr;
+
+    hr = Uninit_DirectDraw_Create(NULL, &pDD, pUnkOuter, TRUE); /* ex? */
+    if (FAILED(hr)) return hr;
+
+    hr = IDirectDraw7_QueryInterface(pDD, iid, ppObj);
+    IDirectDraw_Release(pDD);
+    return hr;
+}
+
+/******************************************************************************
  * DirectDraw ClassFactory
- *
- *  Heavily inspired (well, can you say completely copied :-) ) from DirectSound
- *
  */
 typedef struct {
-    /* IUnknown fields */
-    ICOM_VFIELD(IClassFactory);
-    DWORD		ref;
+    ICOM_VFIELD_MULTI(IClassFactory);
+
+    DWORD ref;
+    HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID iid,
+				 LPVOID *ppObj);
 } IClassFactoryImpl;
 
+struct object_creation_info
+{
+    const CLSID *clsid;
+    HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid,
+				 LPVOID *ppObj);
+};
+
+/* There should be more, but these are the only ones listed in the header
+ * file. */
+extern HRESULT DDRAW_CreateDirectDrawClipper(IUnknown *pUnkOuter, REFIID riid,
+					     LPVOID *ppObj);
+
+static const struct object_creation_info object_creation[] =
+{
+    { &CLSID_DirectDraw,       	DDRAW_CreateDirectDraw },
+    { &CLSID_DirectDraw7,	DDRAW_CreateDirectDraw },
+    { &CLSID_DirectDrawClipper,	DDRAW_CreateDirectDrawClipper }
+};
+
 static HRESULT WINAPI 
-DDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
+DDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
+{
     ICOM_THIS(IClassFactoryImpl,iface);
 
-    FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
+    if (IsEqualGUID(riid, &IID_IUnknown)
+	|| IsEqualGUID(riid, &IID_IClassFactory))
+    {
+	IClassFactory_AddRef(iface);
+	*ppobj = This;
+	return S_OK;
+    }
+
+    WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI
-DDCF_AddRef(LPCLASSFACTORY iface) {
+static ULONG WINAPI DDCF_AddRef(LPCLASSFACTORY iface) {
     ICOM_THIS(IClassFactoryImpl,iface);
     return ++(This->ref);
 }
 
 static ULONG WINAPI DDCF_Release(LPCLASSFACTORY iface) {
     ICOM_THIS(IClassFactoryImpl,iface);
-    /* static class, won't be  freed */
-    return --(This->ref);
+
+    ULONG ref = --This->ref;
+
+    if (ref == 0)
+	HeapFree(GetProcessHeap(), 0, This);
+
+    return ref;
 }
 
+
 static HRESULT WINAPI DDCF_CreateInstance(
 	LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
 ) {
     ICOM_THIS(IClassFactoryImpl,iface);
 
     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
-    if ( ( IsEqualGUID( &IID_IDirectDraw,  riid ) ) ||
-	 ( IsEqualGUID( &IID_IDirectDraw2, riid ) ) ||
-	 ( IsEqualGUID( &IID_IDirectDraw4, riid ) ) ) {
-	    /* FIXME: reuse already created DirectDraw if present? */
-	    return DirectDrawCreate((LPGUID) riid,(LPDIRECTDRAW*)ppobj,pOuter);
-    }
-    return CLASS_E_CLASSNOTAVAILABLE;
+
+    return This->pfnCreateInstance(pOuter, riid, ppobj);
 }
 
 static HRESULT WINAPI DDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
@@ -427,7 +380,6 @@
     DDCF_CreateInstance,
     DDCF_LockServer
 };
-static IClassFactoryImpl DDRAW_CF = {&DDCF_Vtbl, 1 };
 
 /*******************************************************************************
  * DllGetClassObject [DDRAW.13]
@@ -448,14 +400,37 @@
  */
 DWORD WINAPI DDRAW_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
 {
+    int i;
+    IClassFactoryImpl *factory;
+
     TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
-    if ( IsEqualGUID( &IID_IClassFactory, riid ) ) {
-    	*ppv = (LPVOID)&DDRAW_CF;
-	IClassFactory_AddRef((IClassFactory*)*ppv);
-	return S_OK;
+
+    if ( !IsEqualGUID( &IID_IClassFactory, riid )
+	 && ! IsEqualGUID( &IID_IUnknown, riid) )
+	return E_NOINTERFACE;
+
+    for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
+    {
+	if (IsEqualGUID(&object_creation[i].clsid, rclsid))
+	    break;
     }
-    FIXME("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
-    return CLASS_E_CLASSNOTAVAILABLE;
+
+    if (i == sizeof(object_creation)/sizeof(object_creation[0]))
+    {
+	FIXME("%s: no class found.\n", debugstr_guid(rclsid));
+	return CLASS_E_CLASSNOTAVAILABLE;
+    }
+
+    factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
+    if (factory == NULL) return E_OUTOFMEMORY;
+
+    ICOM_INIT_INTERFACE(factory, IClassFactory, DDCF_Vtbl);
+    factory->ref = 1;
+
+    factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
+
+    *ppv = ICOM_INTERFACE(factory, IClassFactory);
+    return S_OK;
 }
 
 
@@ -470,3 +445,89 @@
     FIXME("(void): stub\n");
     return S_FALSE;
 }
+
+/******************************************************************************
+ * Initialisation
+ */
+
+/* Choose which driver is considered the primary display driver. It will
+ * be created when we get a NULL guid for the DirectDrawCreate(Ex). */
+static int DDRAW_ChooseDefaultDriver(void)
+{
+    int i;
+    int best = 0;
+    int best_score = 0;
+
+    assert(DDRAW_num_drivers > 0);
+
+    /* This algorithm is really stupid. */
+    for (i=0; i < DDRAW_num_drivers; i++)
+    {
+	if (DDRAW_drivers[i]->preference > best_score)
+	{
+	    best_score = DDRAW_drivers[i]->preference;
+	    best = i;
+	}
+    }
+
+    assert(best_score > 0);
+
+    return best;
+}
+
+BOOL WINAPI DDRAW_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    /* If we were sufficiently cool, DDraw drivers would just be COM
+     * objects, registered with a particular component category. */
+
+    DDRAW_User_Init(hInstDLL, fdwReason, lpv);
+
+#ifdef HAVE_LIBXXF86VM
+    DDRAW_XVidMode_Init(hInstDLL, fdwReason, lpv);
+#endif
+#ifdef HAVE_LIBXXF86DGA2
+    DDRAW_XF86DGA2_Init(hInstDLL, fdwReason, lpv);
+#endif
+
+    if (DDRAW_num_drivers > 0)
+	DDRAW_default_driver = DDRAW_ChooseDefaultDriver();
+
+    return TRUE;
+}
+
+/* Register a direct draw driver. This should be called from your init
+ * function. (That's why there is no locking: your init func is called from
+ * our DllInit, which is serialised.) */
+void DDRAW_register_driver(const ddraw_driver *driver)
+{
+    int i;
+
+    for (i = 0; i < DDRAW_num_drivers; i++)
+    {
+	if (DDRAW_drivers[i] == driver)
+	{
+	    ERR("Driver reregistering %p\n", driver);
+	    return;
+	}
+    }
+
+    if (DDRAW_num_drivers == sizeof(DDRAW_drivers)/sizeof(DDRAW_drivers[0]))
+    {
+	ERR("too many DDRAW drivers\n");
+	return;
+    }
+
+    DDRAW_drivers[DDRAW_num_drivers++] = driver;
+}
+
+/* This totally doesn't belong here. */
+LONG DDRAW_width_bpp_to_pitch(DWORD width, DWORD bpp)
+{
+    LONG pitch;
+
+    assert(bpp != 0); /* keeps happening... */
+
+    if (bpp == 15) bpp = 16;
+    pitch = width * (bpp / 8);
+    return pitch + (8 - (pitch % 8)) % 8;
+}
diff --git a/dlls/ddraw/mesa_private.h b/dlls/ddraw/mesa_private.h
index 5aa5c94..398a0fd 100644
--- a/dlls/ddraw/mesa_private.h
+++ b/dlls/ddraw/mesa_private.h
@@ -14,8 +14,6 @@
 
 #undef USE_OSMESA
 
-#include "x11_private.h"
-
 /*****************************************************************************
  * IDirect3DLight MESA private structure
  */
@@ -110,8 +108,8 @@
 		      DWORD dwRenderState, RenderState *rs) ;
 
 /* All non-static functions 'exported' by various sub-objects */
-extern LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurface4Impl* surf);
-extern LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurface4Impl* surf);
+extern LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurfaceImpl* surf);
+extern LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurfaceImpl* surf);
 
 extern LPDIRECT3DLIGHT d3dlight_create_dx3(IDirect3DImpl* d3d1);
 extern LPDIRECT3DLIGHT d3dlight_create(IDirect3D2Impl* d3d2);
@@ -129,8 +127,8 @@
 extern int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) ;
 extern int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d);
 
-extern LPDIRECT3DTEXTURE2 mesa_d3dtexture2_create(IDirectDrawSurface4Impl*);
-extern LPDIRECT3DTEXTURE mesa_d3dtexture_create(IDirectDrawSurface4Impl*);
+extern LPDIRECT3DTEXTURE2 mesa_d3dtexture2_create(IDirectDrawSurfaceImpl*);
+extern LPDIRECT3DTEXTURE mesa_d3dtexture_create(IDirectDrawSurfaceImpl*);
 
 static const GUID WINE_UNUSED IID_D3DDEVICE2_OpenGL = {
   0x39a0da38,
diff --git a/dlls/ddraw/struct_convert.c b/dlls/ddraw/struct_convert.c
new file mode 100644
index 0000000..929e6d4
--- /dev/null
+++ b/dlls/ddraw/struct_convert.c
@@ -0,0 +1,28 @@
+/*	ddraw/d3d structure version conversion
+ *
+ * Copyright 2000 TransGaming Technologies Inc.
+ */
+
+#include <ddraw.h>
+
+#include <string.h>
+
+#include "ddraw_private.h"
+
+void DDRAW_Convert_DDSCAPS_1_To_2(const DDSCAPS* pIn, DDSCAPS2* pOut)
+{
+    /* 2 adds three additional caps fields to the end. Both versions
+     * are unversioned. */
+    pOut->dwCaps = pIn->dwCaps;
+    pOut->dwCaps2 = 0;
+    pOut->dwCaps3 = 0;
+    pOut->dwCaps4 = 0;
+}
+
+void DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(const DDDEVICEIDENTIFIER* pIn,
+					     DDDEVICEIDENTIFIER2* pOut)
+{
+    /* 2 adds a dwWHQLLevel field to the end. Both structures are
+     * unversioned. */
+    memcpy(pOut, pIn, sizeof(*pOut));
+}
diff --git a/dlls/ddraw/x11.c b/dlls/ddraw/x11.c
deleted file mode 100644
index a3902ab..0000000
--- a/dlls/ddraw/x11.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*		DirectDraw using DGA or Xlib(XSHM)
- *
- * Copyright 1997-1999 Marcus Meissner
- * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
- */
-#include "config.h"
-
-#include <unistd.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "winerror.h"
-#include "options.h"
-#include "debugtools.h"
-#include "ddraw.h"
-
-DEFAULT_DEBUG_CHANNEL(ddraw);
-
-#include "x11_private.h"
-
-#ifdef HAVE_LIBXXSHM
-int XShmErrorFlag = 0;
-#endif
-
-static inline BOOL get_option( const char *name, BOOL def ) {
-    return PROFILE_GetWineIniBool( "x11drv", name, def );
-}
-
-static BOOL
-DDRAW_XSHM_Available(void) {
-#ifdef HAVE_LIBXXSHM
-    if (get_option( "UseXShm", 1 )) {
-	if (TSXShmQueryExtension(display)) {
-	    int		major,minor;
-	    Bool	shpix;
-
-	    if (TSXShmQueryVersion(display, &major, &minor, &shpix))
-		return TRUE;
-	}
-    }
-#endif
-    return FALSE;
-}
-
-#ifdef HAVE_XVIDEO
-static BOOL
-DDRAW_XVIDEO_Available(x11_dd_private *x11ddp) {
-  unsigned int p_version, p_release, p_request_base, p_event_base, p_error_base;
-  
-  if (TSXvQueryExtension(display, &p_version, &p_release, &p_request_base,
-		       &p_event_base, &p_error_base) == Success) {
-    XvAdaptorInfo *ai;
-    int num_adaptators, i, default_port;
-    
-    if ((p_version < 2) || ((p_version == 2) && (p_release < 2))) {
-      TRACE("XVideo extension does NOT support needed features (need version 2.2) !\n");
-      return FALSE;
-    }
-
-    if (TSXvQueryAdaptors(display, X11DRV_GetXRootWindow(), &num_adaptators, &ai) != Success) {
-      TRACE("Failed to get list of adaptators.\n");
-      return FALSE;
-    }
-    if (num_adaptators == 0) {
-      TRACE("No XVideo supporting adaptators found.\n");
-      return FALSE;
-    }
-
-    default_port = PROFILE_GetWineIniInt("x11drv", "XVideoPort", -1);
-    for (i = 0; i < num_adaptators; i++) {
-      if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask)) {
-	/* This supports everything I want : XvImages and the possibility to put something */
-	if (default_port == -1) {
-	  default_port = ai[i].base_id;
-	  break;
-	} else {
-	  if ((ai[i].base_id <= default_port) &&
-	      ((ai[i].base_id + ai[i].num_ports) > default_port)) {
-	    break;
-	  }
-	}
-      }
-    }
-    if (i == num_adaptators) {
-      if (default_port != -1) {
-	ERR("User specified port (%d) not found.\n", default_port);
-      } else {
-	TRACE("No input + image capable device found.\n");
-      }
-      TSXvFreeAdaptorInfo(ai);
-      return FALSE;
-    }
-    x11ddp->port_id = default_port;
-
-    TRACE("XVideo support available (using version %d.%d)\n", p_version, p_release);
-    TSXvFreeAdaptorInfo(ai);
-    return TRUE;
-  }
-  return FALSE;
-}
-#endif
-
-static HRESULT X11_Create( LPDIRECTDRAW *lplpDD ) {
-    IDirectDrawImpl*	ddraw;
-    int			depth;
-    x11_dd_private	*x11priv;
-
-    if (lplpDD == NULL) /* Testing ... this driver works all the time */
-	return DD_OK;
-
-    *lplpDD = (LPDIRECTDRAW)HeapAlloc(
-	GetProcessHeap(),
-	HEAP_ZERO_MEMORY,
-	sizeof(IDirectDrawImpl)
-    );
-    ddraw = (IDirectDrawImpl*)*lplpDD;
-    ICOM_VTBL(ddraw)= &xlib_ddvt;
-    ddraw->ref	= 1;
-
-    ddraw->d = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*(ddraw->d)));
-    ddraw->d->ref = 1;
-    ddraw->d->private	= HeapAlloc(
-	GetProcessHeap(),
-	HEAP_ZERO_MEMORY,
-	sizeof(x11_dd_private)
-    );
-    x11priv = (x11_dd_private*)ddraw->d->private;
-
-    /* At DirectDraw creation, the depth is the default depth */
-    depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
-
-    switch (_common_depth_to_pixelformat(depth,(LPDIRECTDRAW)ddraw)) {
-    case -2: ERR("no depth conversion mode for depth %d found\n",depth); break;
-    case -1: WARN("No conversion needed for depth %d.\n",depth); break;
-    case 0: MESSAGE("Conversion needed from %d.\n",depth); break;
-    }
-
-    ddraw->d->height = GetSystemMetrics(SM_CYSCREEN);
-    ddraw->d->width = GetSystemMetrics(SM_CXSCREEN);
-#ifdef HAVE_LIBXXSHM
-    /* Test if XShm is available. */
-    if ((x11priv->xshm_active = DDRAW_XSHM_Available())) {
-	x11priv->xshm_compl = 0;
-	TRACE("Using XShm extension.\n");
-    }
-#endif
-
-#ifdef HAVE_XVIDEO
-    /* Test if XVideo support is available */
-    if ((x11priv->xvideo_active = DDRAW_XVIDEO_Available(x11priv))) {
-      TRACE("Using XVideo extension on port '%ld'.\n", x11priv->port_id);
-    }
-#endif
-    return DD_OK;
-}
-
-/* Where do these GUIDs come from?  mkuuid.
- * They exist solely to distinguish between the targets Wine support,
- * and should be different than any other GUIDs in existence.
- */
-static GUID X11_DirectDraw_GUID = { /* 1574a740-dc61-11d1-8407-f7875a7d1879 */
-    0x1574a740,
-    0xdc61,
-    0x11d1,
-    {0x84, 0x07, 0xf7, 0x87, 0x5a, 0x7d, 0x18, 0x79}
-};
-
-ddraw_driver x11_driver = {
-    &X11_DirectDraw_GUID,
-    "display",
-    "WINE X11 DirectDraw Driver",
-    50,
-    X11_Create
-}; 
-
-DECL_GLOBAL_CONSTRUCTOR(X11_register) { ddraw_register_driver(&x11_driver); }
diff --git a/dlls/ddraw/x11_private.h b/dlls/ddraw/x11_private.h
deleted file mode 100644
index e135fa8..0000000
--- a/dlls/ddraw/x11_private.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef __WINE_DDRAW_X11_PRIVATE_H
-#define __WINE_DDRAW_X11_PRIVATE_H
-
-/* This file contains all X11 private and specific definitions.
- * It may also be used by all ports that reuse X11 stuff (like XF86 DGA)
- */
-#include "config.h"
-#include "ts_xlib.h"
-#include "ts_xutil.h"
-
-#ifdef HAVE_LIBXXSHM
-# include <sys/types.h>
-# ifdef HAVE_SYS_IPC_H
-#  include <sys/ipc.h>
-# endif
-# ifdef HAVE_SYS_SHM_H
-#  include <sys/shm.h>
-# endif
-# include "ts_xshm.h"
-#endif /* defined(HAVE_LIBXXSHM) */
-
-#ifdef HAVE_LIBXXF86VM
-# include "ts_xf86vmode.h"
-extern XF86VidModeModeInfo *orig_mode;
-#endif /* defined(HAVE_LIBXXF86VM) */
-
-extern void xf86vmode_setdisplaymode(DWORD,DWORD);
-extern void xf86vmode_restore();
-
-#ifdef HAVE_XVIDEO
-#include "ts_xvideo.h"
-#else
-/* Fake type so that NOT to have too many #ifdef XVideo lying around */
-typedef int XvImage;
-#endif
-
-#include "x11drv.h"
-
-#include "ddraw_private.h"
-
-#include "wine_gl.h"
-
-extern ICOM_VTABLE(IDirectDraw)		xlib_ddvt;
-extern ICOM_VTABLE(IDirectDraw2)        xlib_dd2vt;
-extern ICOM_VTABLE(IDirectDraw4)        xlib_dd4vt;
-extern ICOM_VTABLE(IDirectDraw7)        xlib_dd7vt;
-extern ICOM_VTABLE(IDirectDrawPalette)	xlib_ddpalvt;
-extern ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt;
-
-typedef struct x11_dd_private {
-#ifdef HAVE_LIBXXSHM
-    int xshm_active, xshm_compl;
-#endif /* defined(HAVE_LIBXXSHM) */
-#ifdef HAVE_XVIDEO
-    BOOL xvideo_active;
-    XvPortID port_id;
-#endif
-    Window drawable;
-    void *device_capabilities;
-} x11_dd_private;
-
-typedef struct x11_dp_private {
-    BOOL	installed;	/* is colormap installed */
-    Colormap	cm;		/* the X11 Colormap associated */
-} x11_dp_private;
-
-extern HRESULT WINAPI Xlib_IDirectDrawPaletteImpl_SetEntries(LPDIRECTDRAWPALETTE,DWORD,DWORD,DWORD,LPPALETTEENTRY);
-extern ULONG WINAPI Xlib_IDirectDrawPaletteImpl_Release(LPDIRECTDRAWPALETTE iface);
-
-typedef struct x11_ds_private {
-    BOOL is_overlay;
-    union {
-      XImage	*image;
-      struct {
-	/* The 'image' field should be in FIRST !!!! The Flip function depends on that... */
-	XvImage *image;
-	BOOL shown;
-	RECT src_rect;
-	RECT dst_rect;
-	LPDIRECTDRAWSURFACE dest_surface;
-      } overlay;
-    } info; 
-#ifdef HAVE_LIBXXSHM
-    XShmSegmentInfo	shminfo;
-#endif
-    int		*oldDIBmap;
-    BOOL         opengl_flip;
-} x11_ds_private;
-
-#ifdef HAVE_LIBXXSHM
-extern int XShmErrorFlag;
-#endif
-#endif /* __WINE_DDRAW_X11_PRIVATE_H */
diff --git a/documentation/ddraw.txt b/documentation/ddraw.txt
new file mode 100644
index 0000000..830eab1
--- /dev/null
+++ b/documentation/ddraw.txt
@@ -0,0 +1,134 @@
+This is an outline of the architecture. Many details are
+skipped, but hopefully this is useful.
+
+By Andrew Lewycky <andrew@transgaming.com>
+(with updates by Ove Kåven <ovek@transgaming.com>)
+
+
+* DirectDraw inheritance tree
+
+        Main
+         |
+        User
+         |-----------\
+        XVidMode    DGA2
+
+Most of the DirectDraw functionality is implemented in a common base
+class. Derived classes are responsible for providing display
+mode functions (Enum, Set, Restore), GetCaps, GetDevice identifier
+and internal functions called to create primary and backbuffer
+surfaces.
+
+User provides for DirectDraw capabilities based on drawing to a
+Wine window. It uses the User DirectDrawSurface implementation
+for primary and backbuffer surfaces.
+
+XVidMode attempt to use the XFree86 VidMode extension to set the
+display resolution to match the parameters to SetDisplayMode.
+
+DGA2 attempt to use the XFree86 DGA 2.x extension to set the
+display resolution and direct access to the framebuffer, if the
+full-screen-exclusive cooperative level is used. If not, it just
+uses the User implementation.
+
+
+* DirectDrawSurface inheritance tree
+
+        Main
+         |--------------\
+         |              |
+        DIB        Fake Z-Buffer
+         |
+         |------\---------\
+         |      |         |
+        User   DGA2   DIBTexture
+
+Main provides a very simple base class that does not implement any of
+the image-related functions. Therefore it does not place any
+constraints on how the surface data is stored.
+
+DIB stores the surface data in a DIB section. It is used by the Main
+DirectDraw driver to create off-screen surfaces.
+
+User implements primary and backbuffer surfaces for the User DirectDraw
+driver. If it is a primary surface, it will attempt to keep itself
+synchronized to the window.
+
+DGA2 surfaces claims an appropriate section of framebuffer space and
+lets DIB build its DIB section on top of it.
+
+Fake Z-Buffer surfaces are used by Direct3D to indicate that a primary
+surface has an associated z-buffer. For a first implementation, it
+doesn't need to store any image data since it is just a placeholder.
+
+(Actually 3D programs will rarely use Lock or GetDC on primary
+surfaces, backbuffers or z-buffers so we may want to arrange for
+lazy allocation of the DIB sections.)
+
+
+* Interface Thunks
+
+Only the most recent version of an interface needs to be implemented.
+Other versions are handled by having thunks convert their parameters
+and call the root version.
+
+Not all interface versions have thunks. Some versions could be combined
+because their parameters were compatible. For example if a structure
+changes but the structure has a dwSize field, methods using that structure
+are compatible, as long as the implementation remembers to take the dwSize
+into account.
+
+Interface thunks for Direct3D are more complicated since the paradigm
+changed between versions.
+
+
+* Logical Object Layout
+
+The objects are split into the generic part (essentially the fields for
+Main) and a private part. This is necessary because some objects
+can be created with CoCreateInstance, then Initialized later. Only
+at initialisation time do we know which class to use. Each class
+except Main declares a Part structure and adds that to its Impl.
+
+For example, the DIBTexture DirectDrawSurface implementation looks
+like this:
+
+struct DIBTexture_DirectDrawSurfaceImpl_Part
+{
+        union DIBTexture_data data; /*declared in the real header*/
+};
+
+typedef struct
+{
+        struct DIB_DirectDrawSurfaceImpl_Part dib;
+        struct DIBTexture_DirectDrawSurfaceImpl_Part dibtexture;
+} DIBTexture_DirectDrawSurfaceImpl;
+
+So the DIBTexture surface class is derived from the DIB surface
+class and it adds one piece of data, a union.
+
+Main does not have a Part structure. Its fields are stored in
+IDirectDrawImpl/IDirectDrawSurfaceImpl.
+
+To access private data, one says
+
+DIBTexture_DirectDrawSurfaceImpl* priv = This->private;
+do_something_with(priv->dibtexture.data);
+
+
+* Creating Objects
+
+Classes have two functions relevant to object creation, Create and
+Construct. To create a new object, the class' Create function is
+called. It allocates enough memory for IDirectDrawImpl or
+IDirectDrawSurfaceImpl as well as the private data for derived
+classes and then calls Construct.
+
+Each class's Construct function calls the base class's Construct,
+then does the necessary initialization.
+
+For example, creating a primary surface with the user ddraw driver
+calls User_DirectDrawSurface_Create which allocates memory for the
+object and calls User_DirectDrawSurface_Construct to initialize it.
+This calls DIB_DirectDrawSurface_Construct which calls
+Main_DirectDrawSurface_Construct.
diff --git a/include/acconfig.h b/include/acconfig.h
index 8dc758f..91b3d56 100644
--- a/include/acconfig.h
+++ b/include/acconfig.h
@@ -129,5 +129,8 @@
 /* Define if the X libraries support XVideo */
 #undef HAVE_XVIDEO
 
+/* Define if Mesa's OSMesa (off-screen rendering) library is present */
+#undef HAVE_OSMESA
+
 /* Define if Linux-style gethostbyname_r and gethostbyaddr_r are available */
 #undef HAVE_LINUX_GETHOSTBYNAME_R_6
diff --git a/include/config.h.in b/include/config.h.in
index e1839df..27c2df3 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -164,6 +164,9 @@
 /* Define if the X libraries support XVideo */
 #undef HAVE_XVIDEO
 
+/* Define if Mesa's OSMesa (off-screen rendering) library is present */
+#undef HAVE_OSMESA
+
 /* Define if Linux-style gethostbyname_r and gethostbyaddr_r are available */
 #undef HAVE_LINUX_GETHOSTBYNAME_R_6
 
@@ -290,6 +293,9 @@
 /* Define if you have the <GL/glx.h> header file.  */
 #undef HAVE_GL_GLX_H
 
+/* Define if you have the <GL/osmesa.h> header file.  */
+#undef HAVE_GL_OSMESA_H
+
 /* Define if you have the <X11/XKBlib.h> header file.  */
 #undef HAVE_X11_XKBLIB_H
 
diff --git a/include/ddraw.h b/include/ddraw.h
index dba5a31..d71260a 100644
--- a/include/ddraw.h
+++ b/include/ddraw.h
@@ -3,14 +3,14 @@
 
 #include "windef.h" /* LARGE_INTEGER ... */
 #include "wingdi.h" /* PALETTE stuff ... */
-#include "wine/obj_base.h"
+#include "objbase.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* defined(__cplusplus) */
 
 #ifndef	DIRECTDRAW_VERSION
-#define	DIRECTDRAW_VERSION	0x0500
+#define	DIRECTDRAW_VERSION	0x0700
 #endif /* DIRECTDRAW_VERSION */
 
 /*****************************************************************************
@@ -225,6 +225,14 @@
 #define DDGBS_CANBLT				0x00000001
 #define DDGBS_ISBLTDONE				0x00000002
 
+/* dwFlags for IDirectDrawSurface7::GetFlipStatus */
+#define DDGFS_CANFLIP		1L
+#define DDGFS_ISFLIPDONE	2L
+
+/* dwFlags for IDirectDrawSurface7::SetPrivateData */
+#define DDSPD_IUNKNOWNPTR	1L
+#define DDSPD_VOLATILE		2L
+
 /* DDSCAPS.dwCaps */
 /* reserved1, was 3d capable */
 #define DDSCAPS_RESERVED1		0x00000001
@@ -703,25 +711,35 @@
 	DWORD	dwYUVBitCount;          /* C: how many bits per pixel */
 	DWORD	dwZBufferBitDepth;      /* C: how many bits for z buffers */
 	DWORD	dwAlphaBitDepth;        /* C: how many bits for alpha channels*/
-    } DUMMYUNIONNAME;
+	DWORD	dwLuminanceBitCount;
+	DWORD	dwBumpBitCount;
+    } DUMMYUNIONNAME1;
     union {
 	DWORD	dwRBitMask;             /* 10: mask for red bit*/
 	DWORD	dwYBitMask;             /* 10: mask for Y bits*/
-    } DUMMYUNIONNAME1;
+	DWORD	dwStencilBitDepth;
+	DWORD	dwLuminanceBitMask;
+	DWORD	dwBumpDuBitMask;
+    } DUMMYUNIONNAME2;
     union {
 	DWORD	dwGBitMask;             /* 14: mask for green bits*/
 	DWORD	dwUBitMask;             /* 14: mask for U bits*/
-    } DUMMYUNIONNAME2;
+	DWORD	dwZBitMask;
+	DWORD	dwBumpDvBitMask;
+    } DUMMYUNIONNAME3;
     union {
 	DWORD   dwBBitMask;             /* 18: mask for blue bits*/
 	DWORD   dwVBitMask;             /* 18: mask for V bits*/
-    } DUMMYUNIONNAME3;
+	DWORD	dwStencilBitMask;
+	DWORD	dwBumpLuminanceBitMask;
+    } DUMMYUNIONNAME4;
     union {
     	DWORD	dwRGBAlphaBitMask;	/* 1C: mask for alpha channel */
     	DWORD	dwYUVAlphaBitMask;	/* 1C: mask for alpha channel */
+	DWORD	dwLuminanceAlphaBitMask;
 	DWORD	dwRGBZBitMask;		/* 1C: mask for Z channel */
 	DWORD	dwYUVZBitMask;		/* 1C: mask for Z channel */
-    } DUMMYUNIONNAME4;
+    } DUMMYUNIONNAME5;
     					/* 20: next structure */
 } DDPIXELFORMAT,*LPDDPIXELFORMAT;
 
@@ -920,19 +938,19 @@
 	DWORD	dwFlags;	/* 4: determines what fields are valid*/
 	DWORD	dwHeight;	/* 8: height of surface to be created*/
 	DWORD	dwWidth;	/* C: width of input surface*/
-	LONG	lPitch;		/*10: distance to start of next line (return value only)*/
+	union {
+		LONG	lPitch;	/* 10: distance to start of next line (return value only)*/
+		DWORD	dwLinearSize;
+	} DUMMYUNIONNAME1;
 	DWORD	dwBackBufferCount;/* 14: number of back buffers requested*/
 	union {
 		DWORD	dwMipMapCount;/* 18:number of mip-map levels requested*/
 		DWORD	dwZBufferBitDepth;/*18: depth of Z buffer requested*/
 		DWORD	dwRefreshRate;/* 18:refresh rate (used when display mode is described)*/
-	} DUMMYUNIONNAME;		
+	} DUMMYUNIONNAME2;		
 	DWORD	dwAlphaBitDepth;/* 1C:depth of alpha buffer requested*/
 	DWORD	dwReserved;	/* 20:reserved*/
-	union {
-		LPVOID	lpSurface;	/* 24:pointer to the associated surface memory*/
-		DWORD	dwLinearSize;	/* 24:Formless late-allocated optimized surface size*/
-	} DUMMYUNIONNAME1;
+	LPVOID	lpSurface;	/* 24:pointer to the associated surface memory*/
 	DDCOLORKEY	ddckCKDestOverlay;/* 28: CK for dest overlay use*/
 	DDCOLORKEY	ddckCKDestBlt;	/* 30: CK for destination blt use*/
 	DDCOLORKEY	ddckCKSrcOverlay;/* 38: CK for source overlay use*/
@@ -950,13 +968,13 @@
 	union {
 		LONG	lPitch;	      /*10: distance to start of next line (return value only)*/
 		DWORD   dwLinearSize; /*10: formless late-allocated optimized surface size */
-	} DUMMYUNIONNAME;
+	} DUMMYUNIONNAME1;
 	DWORD	dwBackBufferCount;/* 14: number of back buffers requested*/
 	union {
 		DWORD	dwMipMapCount;/* 18:number of mip-map levels requested*/
 		DWORD	dwRefreshRate;/* 18:refresh rate (used when display mode is described)*/
 		DWORD   dwSrcVBHandle;/* 18:source used in VB::Optimize */
-	} DUMMYUNIONNAME2;		
+	} DUMMYUNIONNAME2;
 	DWORD	dwAlphaBitDepth;/* 1C:depth of alpha buffer requested*/
 	DWORD	dwReserved;	/* 20:reserved*/
 	LPVOID	lpSurface;	/* 24:pointer to the associated surface memory*/
@@ -964,16 +982,16 @@
 		DDCOLORKEY	ddckCKDestOverlay; /* 28: CK for dest overlay use*/
 		DWORD 		dwEmptyFaceColor;  /* 28: color for empty cubemap faces */
 	} DUMMYUNIONNAME3;
-	DDCOLORKEY	ddckCKDestBlt;	/* 2C: CK for destination blt use*/
-	DDCOLORKEY	ddckCKSrcOverlay;/* 30: CK for source overlay use*/
-	DDCOLORKEY	ddckCKSrcBlt;	/* 34: CK for source blt use*/
+	DDCOLORKEY	ddckCKDestBlt;	/* 30: CK for destination blt use*/
+	DDCOLORKEY	ddckCKSrcOverlay;/* 38: CK for source overlay use*/
+	DDCOLORKEY	ddckCKSrcBlt;	/* 40: CK for source blt use*/
 
 	union {
-		DDPIXELFORMAT	ddpfPixelFormat;/* 38: pixel format description of the surface*/
-		DWORD 		dwFVF;	/* 38: vertex format description of vertex buffers */	
+		DDPIXELFORMAT	ddpfPixelFormat;/* 48: pixel format description of the surface*/
+		DWORD 		dwFVF;	/* 48: vertex format description of vertex buffers */	
 	} DUMMYUNIONNAME4;
-	DDSCAPS2	ddsCaps;  /* 3C: DDraw surface caps */
-	DWORD		dwTextureStage; /* 40: stage in multitexture cascade */
+	DDSCAPS2	ddsCaps;  /* 68: DDraw surface caps */
+	DWORD		dwTextureStage; /* 78: stage in multitexture cascade */
 } DDSURFACEDESC2,*LPDDSURFACEDESC2;
 
 /* DDCOLORCONTROL.dwFlags */
@@ -1003,8 +1021,9 @@
 DECL_WINELIB_TYPE_AW(LPDDENUMCALLBACK)
 
 typedef HRESULT CALLBACK (*LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID);
-typedef HRESULT CALLBACK (*LPDDENUMMODESCALLBACK7)(LPDDSURFACEDESC2, LPVOID);
+typedef HRESULT CALLBACK (*LPDDENUMMODESCALLBACK2)(LPDDSURFACEDESC2, LPVOID);
 typedef HRESULT CALLBACK (*LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID);
+typedef HRESULT CALLBACK (*LPDDENUMSURFACESCALLBACK2)(LPDIRECTDRAWSURFACE4, LPDDSURFACEDESC2, LPVOID);
 typedef HRESULT CALLBACK (*LPDDENUMSURFACESCALLBACK7)(LPDIRECTDRAWSURFACE7, LPDDSURFACEDESC2, LPVOID);
 
 typedef BOOL CALLBACK (*LPDDENUMCALLBACKEXA)(GUID *, LPSTR, LPSTR, LPVOID, HMONITOR);
@@ -1020,6 +1039,10 @@
 #define DDENUM_DETACHEDSECONDARYDEVICES	0x00000002
 #define DDENUM_NONDISPLAYDEVICES	0x00000004
 
+/* flags for DirectDrawCreate or IDirectDraw::Initialize */
+#define DDCREATE_HARDWAREONLY	1L
+#define DDCREATE_EMULATIONONLY	2L
+
 typedef struct _DDBLTFX
 {
     DWORD       dwSize;                         /* size of structure */
@@ -1036,13 +1059,13 @@
     {
         DWORD   dwZDestConst;                   /* Constant to use as Z buffer for dest */
         LPDIRECTDRAWSURFACE lpDDSZBufferDest;   /* Surface to use as Z buffer for dest */
-    } DUMMYUNIONNAME;
+    } DUMMYUNIONNAME1;
     DWORD       dwZSrcConstBitDepth;            /* Bit depth used to specify Z constant for source */
     union
     {
         DWORD   dwZSrcConst;                    /* Constant to use as Z buffer for src */
         LPDIRECTDRAWSURFACE lpDDSZBufferSrc;    /* Surface to use as Z buffer for src */
-    } DUMMYUNIONNAME1;
+    } DUMMYUNIONNAME2;
     DWORD       dwAlphaEdgeBlendBitDepth;       /* Bit depth used to specify constant for alpha edge blend */
     DWORD       dwAlphaEdgeBlend;               /* Alpha for edge blending */
     DWORD       dwReserved;
@@ -1051,20 +1074,20 @@
     {
         DWORD   dwAlphaDestConst;               /* Constant to use as Alpha Channel */
         LPDIRECTDRAWSURFACE lpDDSAlphaDest;     /* Surface to use as Alpha Channel */
-    } DUMMYUNIONNAME2;
+    } DUMMYUNIONNAME3;
     DWORD       dwAlphaSrcConstBitDepth;        /* Bit depth used to specify alpha constant for source */
     union
     {
         DWORD   dwAlphaSrcConst;                /* Constant to use as Alpha Channel */
         LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      /* Surface to use as Alpha Channel */
-    } DUMMYUNIONNAME3;
+    } DUMMYUNIONNAME4;
     union
     {
         DWORD   dwFillColor;                    /* color in RGB or Palettized */
         DWORD   dwFillDepth;                    /* depth value for z-buffer */
 	DWORD   dwFillPixel;			/* pixel val for RGBA or RGBZ */
         LPDIRECTDRAWSURFACE lpDDSPattern;       /* Surface to use as pattern */
-    } DUMMYUNIONNAME4;
+    } DUMMYUNIONNAME5;
     DDCOLORKEY  ddckDestColorkey;               /* DestColorkey override */
     DDCOLORKEY  ddckSrcColorkey;                /* SrcColorkey override */
 } DDBLTFX,*LPDDBLTFX;
@@ -1100,13 +1123,13 @@
     {
         DWORD   dwAlphaDestConst;               /* Constant to use as alpha channel for dest */
         LPDIRECTDRAWSURFACE lpDDSAlphaDest;     /* Surface to use as alpha channel for dest */
-    } DUMMYUNIONNAME;
+    } DUMMYUNIONNAME1;
     DWORD       dwAlphaSrcConstBitDepth;        /* Bit depth used to specify alpha constant for source */
     union
     {
         DWORD   dwAlphaSrcConst;                /* Constant to use as alpha channel for src */
         LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      /* Surface to use as alpha channel for src */
-    } DUMMYUNIONNAME1;
+    } DUMMYUNIONNAME2;
     DDCOLORKEY  dckDestColorkey;                /* DestColorkey override */
     DDCOLORKEY  dckSrcColorkey;                 /* DestColorkey override */
     DWORD       dwDDFX;                         /* Overlay FX */
@@ -1340,14 +1363,37 @@
  */
 #define ICOM_INTERFACE IDirectDraw4
 #define IDirectDraw4_METHODS \
-    ICOM_METHOD2(HRESULT,GetSurfaceFromDC,    HDC,, LPDIRECTDRAWSURFACE*,) \
+/*0c*/    ICOM_METHOD (HRESULT,Compact) \
+/*10*/    ICOM_METHOD3(HRESULT,CreateClipper,          DWORD,dwFlags, LPDIRECTDRAWCLIPPER*,lplpDDClipper, IUnknown*,pUnkOuter) \
+/*14*/    ICOM_METHOD4(HRESULT,CreatePalette,          DWORD,dwFlags, LPPALETTEENTRY,lpColorTable, LPDIRECTDRAWPALETTE*,lplpDDPalette, IUnknown*,pUnkOuter) \
+/*18*/    ICOM_METHOD3(HRESULT,CreateSurface,          LPDDSURFACEDESC2,lpDDSurfaceDesc, LPDIRECTDRAWSURFACE4*,lplpDDSurface, IUnknown*,pUnkOuter) \
+/*1c*/    ICOM_METHOD2(HRESULT,DuplicateSurface,       LPDIRECTDRAWSURFACE4,lpDDSurface, LPDIRECTDRAWSURFACE4*,lplpDupDDSurface) \
+/*20*/    ICOM_METHOD4(HRESULT,EnumDisplayModes,       DWORD,dwFlags, LPDDSURFACEDESC2,lpDDSurfaceDesc, LPVOID,lpContext, LPDDENUMMODESCALLBACK2,lpEnumModesCallback) \
+/*24*/    ICOM_METHOD4(HRESULT,EnumSurfaces,           DWORD,dwFlags, LPDDSURFACEDESC2,lpDDSD, LPVOID,lpContext, LPDDENUMSURFACESCALLBACK2,lpEnumSurfacesCallback) \
+/*28*/    ICOM_METHOD (HRESULT,FlipToGDISurface) \
+/*2c*/    ICOM_METHOD2(HRESULT,GetCaps,                LPDDCAPS,lpDDDriverCaps, LPDDCAPS,lpDDHELCaps) \
+/*30*/    ICOM_METHOD1(HRESULT,GetDisplayMode,         LPDDSURFACEDESC2,lpDDSurfaceDesc) \
+/*34*/    ICOM_METHOD2(HRESULT,GetFourCCCodes,         LPDWORD,lpNumCodes, LPDWORD,lpCodes) \
+/*38*/    ICOM_METHOD1(HRESULT,GetGDISurface,          LPDIRECTDRAWSURFACE4*,lplpGDIDDSurface) \
+/*3c*/    ICOM_METHOD1(HRESULT,GetMonitorFrequency,    LPDWORD,lpdwFrequency) \
+/*40*/    ICOM_METHOD1(HRESULT,GetScanLine,            LPDWORD,lpdwScanLine) \
+/*44*/    ICOM_METHOD1(HRESULT,GetVerticalBlankStatus, BOOL*,lpbIsInVB) \
+/*48*/    ICOM_METHOD1(HRESULT,Initialize,             GUID*,lpGUID) \
+/*4c*/    ICOM_METHOD (HRESULT,RestoreDisplayMode) \
+/*50*/    ICOM_METHOD2(HRESULT,SetCooperativeLevel,    HWND,hWnd, DWORD,dwFlags) \
+/*54*/    ICOM_METHOD5(HRESULT,SetDisplayMode,         DWORD,dwWidth, DWORD,dwHeight, DWORD,dwBPP, DWORD,dwRefreshRate, DWORD,dwFlags) \
+/*58*/    ICOM_METHOD2(HRESULT,WaitForVerticalBlank,   DWORD,dwFlags, HANDLE,hEvent) \
+          /* added in v2 */ \
+/*5c*/    ICOM_METHOD3(HRESULT,GetAvailableVidMem, LPDDSCAPS2,lpDDCaps, LPDWORD,lpdwTotal, LPDWORD,lpdwFree) \
+    /* added in v4 */ \
+    ICOM_METHOD2(HRESULT,GetSurfaceFromDC,    HDC,, LPDIRECTDRAWSURFACE4*,) \
     ICOM_METHOD (HRESULT,RestoreAllSurfaces) \
     ICOM_METHOD (HRESULT,TestCooperativeLevel) \
     ICOM_METHOD2(HRESULT,GetDeviceIdentifier, LPDDDEVICEIDENTIFIER,, DWORD,)
 #define IDirectDraw4_IMETHODS \
-    IDirectDraw2_IMETHODS \
+    IUnknown_IMETHODS \
     IDirectDraw4_METHODS
-ICOM_DEFINE(IDirectDraw4,IDirectDraw2)
+ICOM_DEFINE(IDirectDraw4,IUnknown)
 #undef ICOM_INTERFACE
 
     /*** IUnknown methods ***/
@@ -1378,7 +1424,7 @@
 /*** IDirectDraw2 methods ***/
 #define IDirectDraw4_GetAvailableVidMem(p,a,b,c) ICOM_CALL3(GetAvailableVidMem,p,a,b,c)
 /*** IDirectDraw4 methods ***/
-#define IDirectDraw4_GetSurfaceFromDC(p,a,b)    ICOM_CALL2(GetSurfaceFromDC,p,a,b,c)
+#define IDirectDraw4_GetSurfaceFromDC(p,a,b)    ICOM_CALL2(GetSurfaceFromDC,p,a,b)
 #define IDirectDraw4_RestoreAllSurfaces(pc)     ICOM_CALL (RestoreAllSurfaces,p)
 #define IDirectDraw4_TestCooperativeLevel(p)    ICOM_CALL (TestCooperativeLevel,p)
 #define IDirectDraw4_GetDeviceIdentifier(p,a,b) ICOM_CALL2(GetDeviceIdentifier,p,a,b)
@@ -1397,7 +1443,7 @@
 /*14*/    ICOM_METHOD4(HRESULT,CreatePalette,          DWORD,dwFlags, LPPALETTEENTRY,lpColorTable, LPDIRECTDRAWPALETTE*,lplpDDPalette, IUnknown*,pUnkOuter) \
 /*18*/    ICOM_METHOD3(HRESULT,CreateSurface,          LPDDSURFACEDESC2,lpDDSurfaceDesc, LPDIRECTDRAWSURFACE7*,lplpDDSurface, IUnknown*,pUnkOuter) \
 /*1c*/    ICOM_METHOD2(HRESULT,DuplicateSurface,       LPDIRECTDRAWSURFACE7,lpDDSurface, LPDIRECTDRAWSURFACE7*,lplpDupDDSurface) \
-/*20*/    ICOM_METHOD4(HRESULT,EnumDisplayModes,       DWORD,dwFlags, LPDDSURFACEDESC2,lpDDSurfaceDesc, LPVOID,lpContext, LPDDENUMMODESCALLBACK7,lpEnumModesCallback) \
+/*20*/    ICOM_METHOD4(HRESULT,EnumDisplayModes,       DWORD,dwFlags, LPDDSURFACEDESC2,lpDDSurfaceDesc, LPVOID,lpContext, LPDDENUMMODESCALLBACK2,lpEnumModesCallback) \
 /*24*/    ICOM_METHOD4(HRESULT,EnumSurfaces,           DWORD,dwFlags, LPDDSURFACEDESC2,lpDDSD, LPVOID,lpContext, LPDDENUMSURFACESCALLBACK7,lpEnumSurfacesCallback) \
 /*28*/    ICOM_METHOD (HRESULT,FlipToGDISurface) \
 /*2c*/    ICOM_METHOD2(HRESULT,GetCaps,                LPDDCAPS,lpDDDriverCaps, LPDDCAPS,lpDDHELCaps) \
@@ -1418,7 +1464,7 @@
 /*60*/    ICOM_METHOD2(HRESULT,GetSurfaceFromDC,    HDC,, LPDIRECTDRAWSURFACE7*,) \
 /*64*/    ICOM_METHOD (HRESULT,RestoreAllSurfaces) \
 /*68*/    ICOM_METHOD (HRESULT,TestCooperativeLevel) \
-/*6c*/    ICOM_METHOD2(HRESULT,GetDeviceIdentifier, LPDDDEVICEIDENTIFIER,, DWORD,) \
+/*6c*/    ICOM_METHOD2(HRESULT,GetDeviceIdentifier, LPDDDEVICEIDENTIFIER2,, DWORD,) \
           /* added in v7 */ \
 /*70*/    ICOM_METHOD3(HRESULT,StartModeTest,    LPSIZE,, DWORD,, DWORD,) \
 /*74*/    ICOM_METHOD2(HRESULT,EvaluateMode,     DWORD,, DWORD *,)
@@ -1456,8 +1502,8 @@
 /*** added in IDirectDraw2 ***/
 #define IDirectDraw7_GetAvailableVidMem(p,a,b,c) ICOM_CALL3(GetAvailableVidMem,p,a,b,c)
 /*** added in IDirectDraw4 ***/
-#define IDirectDraw7_GetSurfaceFromDC(p,a,b)    ICOM_CALL2(GetSurfaceFromDC,p,a,b,c)
-#define IDirectDraw7_RestoreAllSurfaces(pc)     ICOM_CALL (RestoreAllSurfaces,p)
+#define IDirectDraw7_GetSurfaceFromDC(p,a,b)    ICOM_CALL2(GetSurfaceFromDC,p,a,b)
+#define IDirectDraw7_RestoreAllSurfaces(p)     ICOM_CALL (RestoreAllSurfaces,p)
 #define IDirectDraw7_TestCooperativeLevel(p)    ICOM_CALL (TestCooperativeLevel,p)
 #define IDirectDraw7_GetDeviceIdentifier(p,a,b) ICOM_CALL2(GetDeviceIdentifier,p,a,b)
 /*** added in IDirectDraw 7 ***/
@@ -1539,7 +1585,7 @@
 #define IDirectDrawSurface_Lock(p,a,b,c,d)              ICOM_CALL4(Lock,p,a,b,c,d)
 #define IDirectDrawSurface_ReleaseDC(p,a)               ICOM_CALL1(ReleaseDC,p,a)
 #define IDirectDrawSurface_Restore(p)                   ICOM_CALL (Restore,p)
-#define IDirectDrawSurface_SetClipper(p,a,b)            ICOM_CALL1(SetClipper,p,a,b)
+#define IDirectDrawSurface_SetClipper(p,a)              ICOM_CALL1(SetClipper,p,a)
 #define IDirectDrawSurface_SetColorKey(p,a,b)           ICOM_CALL2(SetColorKey,p,a,b)
 #define IDirectDrawSurface_SetOverlayPosition(p,a,b)    ICOM_CALL2(SetOverlayPosition,p,a,b)
 #define IDirectDrawSurface_SetPalette(p,a)              ICOM_CALL1(SetPalette,p,a)
@@ -1629,8 +1675,8 @@
 #define IDirectDrawSurface2_IsLost(p)                    ICOM_CALL (IsLost,p)
 #define IDirectDrawSurface2_Lock(p,a,b,c,d)              ICOM_CALL4(Lock,p,a,b,c,d)
 #define IDirectDrawSurface2_ReleaseDC(p,a)               ICOM_CALL1(ReleaseDC,p,a)
-#define IDirectDrawSurface2_Restore(p,a,b)               ICOM_CALL (Restore,p,a,b)
-#define IDirectDrawSurface2_SetClipper(p,a,b)            ICOM_CALL1(SetClipper,p,a,b)
+#define IDirectDrawSurface2_Restore(p)                   ICOM_CALL (Restore,p)
+#define IDirectDrawSurface2_SetClipper(p,a)              ICOM_CALL1(SetClipper,p,a)
 #define IDirectDrawSurface2_SetColorKey(p,a,b)           ICOM_CALL2(SetColorKey,p,a,b)
 #define IDirectDrawSurface2_SetOverlayPosition(p,a,b)    ICOM_CALL2(SetOverlayPosition,p,a,b)
 #define IDirectDrawSurface2_SetPalette(p,a)              ICOM_CALL1(SetPalette,p,a)
@@ -1726,8 +1772,8 @@
 #define IDirectDrawSurface3_IsLost(p)                    ICOM_CALL (IsLost,p)
 #define IDirectDrawSurface3_Lock(p,a,b,c,d)              ICOM_CALL4(Lock,p,a,b,c,d)
 #define IDirectDrawSurface3_ReleaseDC(p,a)               ICOM_CALL1(ReleaseDC,p,a)
-#define IDirectDrawSurface3_Restore(p,a,b)               ICOM_CALL (Restore,p,a,b)
-#define IDirectDrawSurface3_SetClipper(p,a,b)            ICOM_CALL1(SetClipper,p,a,b)
+#define IDirectDrawSurface3_Restore(p)                   ICOM_CALL (Restore,p)
+#define IDirectDrawSurface3_SetClipper(p,a)              ICOM_CALL1(SetClipper,p,a)
 #define IDirectDrawSurface3_SetColorKey(p,a,b)           ICOM_CALL2(SetColorKey,p,a,b)
 #define IDirectDrawSurface3_SetOverlayPosition(p,a,b)    ICOM_CALL2(SetOverlayPosition,p,a,b)
 #define IDirectDrawSurface3_SetPalette(p,a)              ICOM_CALL1(SetPalette,p,a)
@@ -1784,7 +1830,7 @@
     ICOM_METHOD2(HRESULT,SetColorKey,           DWORD,dwFlags, LPDDCOLORKEY,lpDDColorKey) \
     ICOM_METHOD2(HRESULT,SetOverlayPosition,    LONG,lX, LONG,lY) \
     ICOM_METHOD1(HRESULT,SetPalette,            LPDIRECTDRAWPALETTE,lpDDPalette) \
-    ICOM_METHOD1(HRESULT,Unlock,                LPVOID,lpSurfaceData) \
+    ICOM_METHOD1(HRESULT,Unlock,                LPRECT,lpSurfaceData) \
     ICOM_METHOD5(HRESULT,UpdateOverlay,         LPRECT,lpSrcRect, LPDIRECTDRAWSURFACE4,lpDDDestSurface, LPRECT,lpDestRect, DWORD,dwFlags, LPDDOVERLAYFX,lpDDOverlayFx) \
     ICOM_METHOD1(HRESULT,UpdateOverlayDisplay,  DWORD,dwFlags) \
     ICOM_METHOD2(HRESULT,UpdateOverlayZOrder,   DWORD,dwFlags, LPDIRECTDRAWSURFACE4,lpDDSReference) \
@@ -1835,8 +1881,8 @@
 #define IDirectDrawSurface4_IsLost(p)                    ICOM_CALL (IsLost,p)
 #define IDirectDrawSurface4_Lock(p,a,b,c,d)              ICOM_CALL4(Lock,p,a,b,c,d)
 #define IDirectDrawSurface4_ReleaseDC(p,a)               ICOM_CALL1(ReleaseDC,p,a)
-#define IDirectDrawSurface4_Restore(p,a,b)               ICOM_CALL (Restore,p,a,b)
-#define IDirectDrawSurface4_SetClipper(p,a,b)            ICOM_CALL1(SetClipper,p,a,b)
+#define IDirectDrawSurface4_Restore(p)                   ICOM_CALL (Restore,p)
+#define IDirectDrawSurface4_SetClipper(p,a)              ICOM_CALL1(SetClipper,p,a)
 #define IDirectDrawSurface4_SetColorKey(p,a,b)           ICOM_CALL2(SetColorKey,p,a,b)
 #define IDirectDrawSurface4_SetOverlayPosition(p,a,b)    ICOM_CALL2(SetOverlayPosition,p,a,b)
 #define IDirectDrawSurface4_SetPalette(p,a)              ICOM_CALL1(SetPalette,p,a)
@@ -1849,7 +1895,7 @@
 #define IDirectDrawSurface4_PageLock(p,a)       ICOM_CALL1(PageLock,p,a)
 #define IDirectDrawSurface4_PageUnlock(p,a)     ICOM_CALL1(PageUnlock,p,a)
 /*** IDirectDrawSurface3 methods ***/
-#define IDirectDrawSurface4_SetSurfaceDesc(p,a) ICOM_CALL(SetSurfaceDesc,p,a)
+#define IDirectDrawSurface4_SetSurfaceDesc(p,a,b) ICOM_CALL2(SetSurfaceDesc,p,a,b)
 /*** IDirectDrawSurface4 methods ***/
 #define IDirectDrawSurface4_SetPrivateData(p,a,b,c,d) ICOM_CALL4(SetPrivateData,p,a,b,c,d)
 #define IDirectDrawSurface4_GetPrivateData(p,a,b,c)   ICOM_CALL3(GetPrivateData,p,a,b,c)
@@ -1869,8 +1915,8 @@
     ICOM_METHOD3(HRESULT,BltBatch,              LPDDBLTBATCH,lpDDBltBatch, DWORD,dwCount, DWORD,dwFlags) \
     ICOM_METHOD5(HRESULT,BltFast,               DWORD,dwX, DWORD,dwY, LPDIRECTDRAWSURFACE7,lpDDSrcSurface, LPRECT,lpSrcRect, DWORD,dwTrans) \
     ICOM_METHOD2(HRESULT,DeleteAttachedSurface, DWORD,dwFlags, LPDIRECTDRAWSURFACE7,lpDDSAttachedSurface) \
-    ICOM_METHOD2(HRESULT,EnumAttachedSurfaces,  LPVOID,lpContext, LPDDENUMSURFACESCALLBACK,lpEnumSurfacesCallback) \
-    ICOM_METHOD3(HRESULT,EnumOverlayZOrders,    DWORD,dwFlags, LPVOID,lpContext, LPDDENUMSURFACESCALLBACK,lpfnCallback) \
+    ICOM_METHOD2(HRESULT,EnumAttachedSurfaces,  LPVOID,lpContext, LPDDENUMSURFACESCALLBACK7,lpEnumSurfacesCallback) \
+    ICOM_METHOD3(HRESULT,EnumOverlayZOrders,    DWORD,dwFlags, LPVOID,lpContext, LPDDENUMSURFACESCALLBACK7,lpfnCallback) \
     ICOM_METHOD2(HRESULT,Flip,                  LPDIRECTDRAWSURFACE7,lpDDSurfaceTargetOverride, DWORD,dwFlags) \
     ICOM_METHOD2(HRESULT,GetAttachedSurface,    LPDDSCAPS2,lpDDSCaps, LPDIRECTDRAWSURFACE7*,lplpDDAttachedSurface) \
     ICOM_METHOD1(HRESULT,GetBltStatus,          DWORD,dwFlags) \
@@ -1892,7 +1938,7 @@
     ICOM_METHOD2(HRESULT,SetColorKey,           DWORD,dwFlags, LPDDCOLORKEY,lpDDColorKey) \
     ICOM_METHOD2(HRESULT,SetOverlayPosition,    LONG,lX, LONG,lY) \
     ICOM_METHOD1(HRESULT,SetPalette,            LPDIRECTDRAWPALETTE,lpDDPalette) \
-    ICOM_METHOD1(HRESULT,Unlock,                LPVOID,lpSurfaceData) \
+    ICOM_METHOD1(HRESULT,Unlock,                LPRECT,lpSurfaceData) \
     ICOM_METHOD5(HRESULT,UpdateOverlay,         LPRECT,lpSrcRect, LPDIRECTDRAWSURFACE7,lpDDDestSurface, LPRECT,lpDestRect, DWORD,dwFlags, LPDDOVERLAYFX,lpDDOverlayFx) \
     ICOM_METHOD1(HRESULT,UpdateOverlayDisplay,  DWORD,dwFlags) \
     ICOM_METHOD2(HRESULT,UpdateOverlayZOrder,   DWORD,dwFlags, LPDIRECTDRAWSURFACE7,lpDDSReference) \
@@ -1919,6 +1965,61 @@
 ICOM_DEFINE(IDirectDrawSurface7,IUnknown)
 #undef ICOM_INTERFACE
 
+    /*** IUnknown methods ***/
+#define IDirectDrawSurface7_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
+#define IDirectDrawSurface7_AddRef(p)             ICOM_CALL (AddRef,p)
+#define IDirectDrawSurface7_Release(p)            ICOM_CALL (Release,p)
+/*** IDirectDrawSurface (almost) methods ***/
+#define IDirectDrawSurface7_AddAttachedSurface(p,a)      ICOM_CALL1(AddAttachedSurface,p,a)
+#define IDirectDrawSurface7_AddOverlayDirtyRect(p,a)     ICOM_CALL1(AddOverlayDirtyRect,p,a)
+#define IDirectDrawSurface7_Blt(p,a,b,c,d,e)             ICOM_CALL5(Blt,p,a,b,c,d,e)
+#define IDirectDrawSurface7_BltBatch(p,a,b,c)            ICOM_CALL3(BltBatch,p,a,b,c)
+#define IDirectDrawSurface7_BltFast(p,a,b,c,d,e)         ICOM_CALL5(BltFast,p,a,b,c,d,e)
+#define IDirectDrawSurface7_DeleteAttachedSurface(p,a,b) ICOM_CALL2(DeleteAttachedSurface,p,a,b)
+#define IDirectDrawSurface7_EnumAttachedSurfaces(p,a,b)  ICOM_CALL2(EnumAttachedSurfaces,p,a,b)
+#define IDirectDrawSurface7_EnumOverlayZOrders(p,a,b,c)  ICOM_CALL3(EnumOverlayZOrders,p,a,b,c)
+#define IDirectDrawSurface7_Flip(p,a,b)                  ICOM_CALL2(Flip,p,a,b)
+#define IDirectDrawSurface7_GetAttachedSurface(p,a,b)    ICOM_CALL2(GetAttachedSurface,p,a,b)
+#define IDirectDrawSurface7_GetBltStatus(p,a)            ICOM_CALL1(GetBltStatus,p,a)
+#define IDirectDrawSurface7_GetCaps(p,a)                 ICOM_CALL1(GetCaps,p,a)
+#define IDirectDrawSurface7_GetClipper(p,a)              ICOM_CALL1(GetClipper,p,a)
+#define IDirectDrawSurface7_GetColorKey(p,a,b)           ICOM_CALL2(GetColorKey,p,a,b)
+#define IDirectDrawSurface7_GetDC(p,a)                   ICOM_CALL1(GetDC,p,a)
+#define IDirectDrawSurface7_GetFlipStatus(p,a)           ICOM_CALL1(GetFlipStatus,p,a)
+#define IDirectDrawSurface7_GetOverlayPosition(p,a,b)    ICOM_CALL2(GetOverlayPosition,p,a,b)
+#define IDirectDrawSurface7_GetPalette(p,a)              ICOM_CALL1(GetPalette,p,a)
+#define IDirectDrawSurface7_GetPixelFormat(p,a)          ICOM_CALL1(GetPixelFormat,p,a)
+#define IDirectDrawSurface7_GetSurfaceDesc(p,a)          ICOM_CALL1(GetSurfaceDesc,p,a)
+#define IDirectDrawSurface7_Initialize(p,a,b)            ICOM_CALL2(Initialize,p,a,b)
+#define IDirectDrawSurface7_IsLost(p)                    ICOM_CALL (IsLost,p)
+#define IDirectDrawSurface7_Lock(p,a,b,c,d)              ICOM_CALL4(Lock,p,a,b,c,d)
+#define IDirectDrawSurface7_ReleaseDC(p,a)               ICOM_CALL1(ReleaseDC,p,a)
+#define IDirectDrawSurface7_Restore(p)                   ICOM_CALL (Restore,p)
+#define IDirectDrawSurface7_SetClipper(p,a)              ICOM_CALL1(SetClipper,p,a)
+#define IDirectDrawSurface7_SetColorKey(p,a,b)           ICOM_CALL2(SetColorKey,p,a,b)
+#define IDirectDrawSurface7_SetOverlayPosition(p,a,b)    ICOM_CALL2(SetOverlayPosition,p,a,b)
+#define IDirectDrawSurface7_SetPalette(p,a)              ICOM_CALL1(SetPalette,p,a)
+#define IDirectDrawSurface7_Unlock(p,a)                  ICOM_CALL1(Unlock,p,a)
+#define IDirectDrawSurface7_UpdateOverlay(p,a,b,c,d,e)   ICOM_CALL5(UpdateOverlay,p,a,b,c,d,e)
+#define IDirectDrawSurface7_UpdateOverlayDisplay(p,a)    ICOM_CALL1(UpdateOverlayDisplay,p,a)
+#define IDirectDrawSurface7_UpdateOverlayZOrder(p,a,b)   ICOM_CALL2(UpdateOverlayZOrder,p,a,b)
+/*** IDirectDrawSurface2 methods ***/
+#define IDirectDrawSurface7_GetDDInterface(p,a) ICOM_CALL1(GetDDInterface,p,a)
+#define IDirectDrawSurface7_PageLock(p,a)       ICOM_CALL1(PageLock,p,a)
+#define IDirectDrawSurface7_PageUnlock(p,a)     ICOM_CALL1(PageUnlock,p,a)
+/*** IDirectDrawSurface3 methods ***/
+#define IDirectDrawSurface7_SetSurfaceDesc(p,a,b) ICOM_CALL2(SetSurfaceDesc,p,a,b)
+/*** IDirectDrawSurface4 methods ***/
+#define IDirectDrawSurface7_SetPrivateData(p,a,b,c,d) ICOM_CALL4(SetPrivateData,p,a,b,c,d)
+#define IDirectDrawSurface7_GetPrivateData(p,a,b,c)   ICOM_CALL3(GetPrivateData,p,a,b,c)
+#define IDirectDrawSurface7_FreePrivateData(p,a)      ICOM_CALL1(FreePrivateData,p,a)
+#define IDirectDrawSurface7_GetUniquenessValue(p,a)   ICOM_CALL1(GetUniquenessValue,p,a)
+#define IDirectDrawSurface7_ChangeUniquenessValue(p)  ICOM_CALL (ChangeUniquenessValue,p)
+/*** IDirectDrawSurface7 methods ***/
+#define IDirectDrawSurface7_SetPriority(p,a)          ICOM_CALL1(SetPriority,p,a)
+#define IDirectDrawSurface7_GetPriority(p,a)          ICOM_CALL1(GetPriority,p,a)
+#define IDirectDrawSurface7_SetLOD(p,a)               ICOM_CALL1(SetLOD,p,a)
+#define IDirectDrawSurface7_GetLOD(p,a)               ICOM_CALL1(GetLOD,p,a)
 
 /*****************************************************************************
  * IDirectDrawColorControl interface
diff --git a/msdos/vga.c b/msdos/vga.c
index ff70d0f..84c3dab 100644
--- a/msdos/vga.c
+++ b/msdos/vga.c
@@ -100,7 +100,7 @@
     if (!lpddsurf) return 1;
     if (Height) *Height=sdesc.dwHeight;
     if (Width) *Width=sdesc.dwWidth;
-    if (Depth) *Depth=sdesc.ddpfPixelFormat.u.dwRGBBitCount;
+    if (Depth) *Depth=sdesc.ddpfPixelFormat.u1.dwRGBBitCount;
     return 0;
 }
 
@@ -147,16 +147,16 @@
         ERR("could not lock surface!\n");
         return NULL;
     }
-    if (Pitch) *Pitch=sdesc.lPitch;
+    if (Pitch) *Pitch=sdesc.u1.lPitch;
     if (Height) *Height=sdesc.dwHeight;
     if (Width) *Width=sdesc.dwWidth;
-    if (Depth) *Depth=sdesc.ddpfPixelFormat.u.dwRGBBitCount;
-    return sdesc.u1.lpSurface;
+    if (Depth) *Depth=sdesc.ddpfPixelFormat.u1.dwRGBBitCount;
+    return sdesc.lpSurface;
 }
 
 void VGA_Unlock(void)
 {
-    IDirectDrawSurface_Unlock(lpddsurf,sdesc.u1.lpSurface);
+    IDirectDrawSurface_Unlock(lpddsurf,sdesc.lpSurface);
 }
 
 /*** TEXT MODE ***/