Like the AUTORADIOBUTTON, the parent of a RADIOBUTTON style button
[wine] / dlls / ddraw / dsurface / main.c
1 /*              DirectDrawSurface base implementation
2  *
3  * Copyright 1997-2000 Marcus Meissner
4  * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5  */
6 #include "config.h"
7 #include "winerror.h"
8
9
10 #include <unistd.h>
11 #include <assert.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16
17 #include "debugtools.h"
18 #include "ddraw_private.h"
19
20 DEFAULT_DEBUG_CHANNEL(ddraw);
21
22 /******************************************************************************
23  *              IDirectDrawSurface methods
24  *
25  * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
26  * DDS and DDS2 use those functions. (Function calls did not change (except
27  * using different DirectDrawSurfaceX version), just added flags and functions)
28  */
29
30 HRESULT WINAPI IDirectDrawSurface4Impl_Lock(
31     LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
32 ) {
33     ICOM_THIS(IDirectDrawSurface4Impl,iface);
34
35     TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
36         This,lprect,lpddsd,flags,(DWORD)hnd);
37
38     /* DO NOT AddRef the surface! Lock/Unlock must not come in matched pairs
39      * -Marcus Meissner 20000509
40      */
41     if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
42         WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
43                  This,lprect,lpddsd,flags,(DWORD)hnd);
44
45     /* First, copy the Surface description */
46     *lpddsd = This->s.surface_desc;
47     TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
48           lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
49
50     /* If asked only for a part, change the surface pointer */
51     if (lprect) {
52         TRACE(" lprect: %dx%d-%dx%d\n",
53                 lprect->top,lprect->left,lprect->bottom,lprect->right
54         );
55         if ((lprect->top < 0) ||
56             (lprect->left < 0) ||
57             (lprect->bottom < 0) ||
58             (lprect->right < 0)) {
59           ERR(" Negative values in LPRECT !!!\n");
60           return DDERR_INVALIDPARAMS;
61        }
62        
63         lpddsd->u1.lpSurface = (LPVOID) ((char *) This->s.surface_desc.u1.lpSurface +
64                 (lprect->top*This->s.surface_desc.lPitch) +
65                 lprect->left*GET_BPP(This->s.surface_desc));
66     } else {
67         assert(This->s.surface_desc.u1.lpSurface);
68     }
69     return DD_OK;
70 }
71
72 HRESULT WINAPI IDirectDrawSurface4Impl_Unlock(
73     LPDIRECTDRAWSURFACE4 iface,LPVOID surface
74 ) {
75     ICOM_THIS(IDirectDrawSurface4Impl,iface);
76
77     /* DO NOT Release the surface! Lock/Unlock MUST NOT come in matched pairs
78      * Marcus Meissner 20000509
79      */
80     TRACE("(%p)->Unlock(%p)\n",This,surface);
81     return DD_OK;
82 }
83
84 IDirectDrawSurface4Impl* _common_find_flipto(
85     IDirectDrawSurface4Impl* This,IDirectDrawSurface4Impl* flipto
86 ) {
87     int i,j,flipable=0;
88     struct _surface_chain       *chain = This->s.chain;
89
90     /* if there was no override flipto, look for current backbuffer */
91     if (!flipto) {
92         /* walk the flip chain looking for backbuffer */
93         for (i=0;i<chain->nrofsurfaces;i++) {
94             if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP)
95                 flipable++;
96             if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_BACKBUFFER)
97                 flipto = chain->surfaces[i];
98         }
99         /* sanity checks ... */
100         if (!flipto) {
101             if (flipable>1) {
102                 for (i=0;i<chain->nrofsurfaces;i++)
103                     if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FRONTBUFFER)
104                         break;
105                 if (i==chain->nrofsurfaces) {
106                     /* we do not have a frontbuffer either */
107                     for (i=0;i<chain->nrofsurfaces;i++)
108                         if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP) {
109                             SDDSCAPS(chain->surfaces[i])|=DDSCAPS_FRONTBUFFER;
110                             break;
111                         }
112                     for (j=i+1;j<i+chain->nrofsurfaces+1;j++) {
113                         int k = j % chain->nrofsurfaces;
114                         if (SDDSCAPS(chain->surfaces[k]) & DDSCAPS_FLIP) {
115                             SDDSCAPS(chain->surfaces[k])|=DDSCAPS_BACKBUFFER;
116                             flipto = chain->surfaces[k];
117                             break;
118                         }
119                     }
120                 }
121             }
122             if (!flipto)
123                 flipto = This;
124         }
125         TRACE("flipping to %p\n",flipto);
126     }
127     return flipto;
128 }
129
130 static HRESULT _Blt_ColorFill(
131     LPBYTE buf, int width, int height, int bpp, LONG lPitch, DWORD color
132 ) {
133     int x, y;
134     LPBYTE first;
135
136     /* Do first row */
137
138 #define COLORFILL_ROW(type) { \
139     type *d = (type *) buf; \
140     for (x = 0; x < width; x++) \
141         d[x] = (type) color; \
142     break; \
143 }
144
145     switch(bpp) {
146     case 1: COLORFILL_ROW(BYTE)
147     case 2: COLORFILL_ROW(WORD)
148     case 4: COLORFILL_ROW(DWORD)
149     default:
150         FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
151         return DDERR_UNSUPPORTED;
152     }
153
154 #undef COLORFILL_ROW
155
156     /* Now copy first row */
157     first = buf;
158     for (y = 1; y < height; y++) {
159         buf += lPitch;
160         memcpy(buf, first, width * bpp);
161     }
162     return DD_OK;
163 }
164
165 HRESULT WINAPI IDirectDrawSurface4Impl_Blt(
166     LPDIRECTDRAWSURFACE4 iface,LPRECT rdst,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,
167     DWORD dwFlags,LPDDBLTFX lpbltfx
168 ) {
169     ICOM_THIS(IDirectDrawSurface4Impl,iface);
170     RECT                xdst,xsrc;
171     DDSURFACEDESC       ddesc,sdesc;
172     HRESULT             ret = DD_OK;
173     int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
174     int x, y;
175     LPBYTE dbuf, sbuf;
176
177     TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
178
179     if (src) IDirectDrawSurface4_Lock(src, NULL, &sdesc, 0, 0);
180     IDirectDrawSurface4_Lock(iface,NULL,&ddesc,0,0);
181
182     if (TRACE_ON(ddraw)) {
183         if (rdst) TRACE("\tdestrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
184         if (rsrc) TRACE("\tsrcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
185         TRACE("\tflags: ");
186         _dump_DDBLT(dwFlags);
187         if (dwFlags & DDBLT_DDFX) {
188             TRACE("\tblitfx: ");
189             _dump_DDBLTFX(lpbltfx->dwDDFX);
190         }
191     }
192
193     if (rdst) {
194         if ((rdst->top < 0) ||
195             (rdst->left < 0) ||
196             (rdst->bottom < 0) ||
197             (rdst->right < 0)) {
198           ERR(" Negative values in LPRECT !!!\n");
199           goto release;
200         }
201         memcpy(&xdst,rdst,sizeof(xdst));
202     } else {
203         xdst.top        = 0;
204         xdst.bottom     = ddesc.dwHeight;
205         xdst.left       = 0;
206         xdst.right      = ddesc.dwWidth;
207     }
208
209     if (rsrc) {
210         if ((rsrc->top < 0) ||
211             (rsrc->left < 0) ||
212             (rsrc->bottom < 0) ||
213             (rsrc->right < 0)) {
214           ERR(" Negative values in LPRECT !!!\n");
215           goto release;
216         }
217         memcpy(&xsrc,rsrc,sizeof(xsrc));
218     } else {
219         if (src) {
220             xsrc.top    = 0;
221             xsrc.bottom = sdesc.dwHeight;
222             xsrc.left   = 0;
223             xsrc.right  = sdesc.dwWidth;
224         } else {
225             memset(&xsrc,0,sizeof(xsrc));
226         }
227     }
228     if (src) assert(xsrc.bottom <= sdesc.dwHeight);
229     assert(xdst.bottom <= ddesc.dwHeight);
230
231     bpp = GET_BPP(ddesc);
232     srcheight = xsrc.bottom - xsrc.top;
233     srcwidth = xsrc.right - xsrc.left;
234     dstheight = xdst.bottom - xdst.top;
235     dstwidth = xdst.right - xdst.left;
236     width = (xdst.right - xdst.left) * bpp;
237
238     assert(width <= ddesc.lPitch);
239
240     dbuf = (BYTE*)ddesc.u1.lpSurface+(xdst.top*ddesc.lPitch)+(xdst.left*bpp);
241
242     dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
243
244     /* First, all the 'source-less' blits */
245     if (dwFlags & DDBLT_COLORFILL) {
246         ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
247                              ddesc.lPitch, lpbltfx->u4.dwFillColor);
248         dwFlags &= ~DDBLT_COLORFILL;
249     }
250
251     if (dwFlags & DDBLT_DEPTHFILL)
252         FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
253     if (dwFlags & DDBLT_ROP) {
254         /* Catch some degenerate cases here */
255         switch(lpbltfx->dwROP) {
256         case BLACKNESS:
257             ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.lPitch,0);
258             break;
259         case 0xAA0029: /* No-op */
260             break;
261         case WHITENESS:
262             ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.lPitch,~0);
263             break;
264         default: 
265             FIXME("Unsupported raster op: %08lx  Pattern: %p\n", lpbltfx->dwROP, lpbltfx->u4.lpDDSPattern);
266             goto error;
267         }
268         dwFlags &= ~DDBLT_ROP;
269     }
270     if (dwFlags & DDBLT_DDROPS) {
271         FIXME("\tDdraw Raster Ops: %08lx  Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u4.lpDDSPattern);
272     }
273     /* Now the 'with source' blits */
274     if (src) {
275         LPBYTE sbase;
276         int sx, xinc, sy, yinc;
277
278         sbase = (BYTE*)sdesc.u1.lpSurface+(xsrc.top*sdesc.lPitch)+xsrc.left*bpp;
279         xinc = (srcwidth << 16) / dstwidth;
280         yinc = (srcheight << 16) / dstheight;
281
282         if (!dwFlags) {
283             assert(ddesc.lPitch >= width);
284             assert(sdesc.lPitch >= width);
285
286             /* No effects, we can cheat here */
287             if (dstwidth == srcwidth) {
288                 if (dstheight == srcheight) {
289                     /* No stretching in either direction. This needs to be as
290                      * fast as possible */
291                     sbuf = sbase;
292                     for (y = 0; y < dstheight; y++) {
293                         memcpy(dbuf, sbuf, width);
294                         sbuf += sdesc.lPitch;
295                         dbuf += ddesc.lPitch;
296                     }
297                 } else {
298                     /* Stretching in Y direction only */
299                     for (y = sy = 0; y < dstheight; y++, sy += yinc) {
300                         sbuf = sbase + (sy >> 16) * sdesc.lPitch;
301                         memcpy(dbuf, sbuf, width);
302                         dbuf += ddesc.lPitch;
303                     }
304                 }
305             } else {
306                 /* Stretching in X direction */
307                 int last_sy = -1;
308                 for (y = sy = 0; y < dstheight; y++, sy += yinc) {
309                     sbuf = sbase + (sy >> 16) * sdesc.lPitch;
310
311                     assert((sy>>16) < srcheight);
312
313                     if ((sy >> 16) == (last_sy >> 16)) {
314                         /* this sourcerow is the same as last sourcerow -
315                          * copy already stretched row
316                          */
317                         memcpy(dbuf, dbuf - ddesc.lPitch, width);
318                     } else {
319 #define STRETCH_ROW(type) { \
320                     type *s = (type *) sbuf, *d = (type *) dbuf; \
321                     for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
322                     d[x] = s[sx >> 16]; \
323                     break; }
324
325                     switch(bpp) {
326                     case 1: STRETCH_ROW(BYTE)
327                     case 2: STRETCH_ROW(WORD)
328                     case 4: STRETCH_ROW(DWORD)
329                     case 3: {
330                         LPBYTE s,d = dbuf;
331                         for (x = sx = 0; x < dstwidth; x++, sx+= xinc) {
332                             DWORD pixel;
333
334                             s = sbuf+3*(sx>>16);
335                             pixel = (s[0]<<16)|(s[1]<<8)|s[2];
336                             d[0] = (pixel>>16)&0xff;
337                             d[1] = (pixel>> 8)&0xff;
338                             d[2] = (pixel    )&0xff;
339                             d+=3;
340                         }
341                         break;
342                     }
343                     default:
344                         FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
345                         ret = DDERR_UNSUPPORTED;
346                         goto error;
347                     }
348 #undef STRETCH_ROW
349                     }
350                     dbuf += ddesc.lPitch;
351                     last_sy = sy;
352                 }
353             }
354         } else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST)) {
355             DWORD keylow, keyhigh;
356
357             if (dwFlags & DDBLT_KEYSRC) {
358                 keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
359                 keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
360             } else {
361                 /* I'm not sure if this is correct */
362                 FIXME("DDBLT_KEYDEST not fully supported yet.\n");
363                 keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
364                 keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
365             }
366
367
368             for (y = sy = 0; y < dstheight; y++, sy += yinc) {
369                 sbuf = sbase + (sy >> 16) * sdesc.lPitch;
370
371 #define COPYROW_COLORKEY(type) { \
372                 type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
373                 for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
374                     tmp = s[sx >> 16]; \
375                     if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
376                 } \
377                 break; }
378
379                 switch (bpp) {
380                 case 1: COPYROW_COLORKEY(BYTE)
381                 case 2: COPYROW_COLORKEY(WORD)
382                 case 4: COPYROW_COLORKEY(DWORD)
383                 default:
384                     FIXME("%s color-keyed blit not implemented for bpp %d!\n",
385                     (dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
386                     ret = DDERR_UNSUPPORTED;
387                     goto error;
388                 }
389                 dbuf += ddesc.lPitch;
390             }
391 #undef COPYROW_COLORKEY
392             dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST);
393         }
394     }
395
396 error:
397     if (dwFlags && FIXME_ON(ddraw)) {
398         FIXME("\tUnsupported flags: ");
399         _dump_DDBLT(dwFlags);
400     }
401
402 release:
403     IDirectDrawSurface4_Unlock(iface,ddesc.u1.lpSurface);
404     if (src) IDirectDrawSurface4_Unlock(src,sdesc.u1.lpSurface);
405     return DD_OK;
406 }
407
408 HRESULT WINAPI IDirectDrawSurface4Impl_BltFast(
409     LPDIRECTDRAWSURFACE4 iface,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE4 src,
410     LPRECT rsrc,DWORD trans
411 ) {
412     ICOM_THIS(IDirectDrawSurface4Impl,iface);
413     int                 bpp, w, h, x, y;
414     DDSURFACEDESC       ddesc,sdesc;
415     HRESULT             ret = DD_OK;
416     LPBYTE              sbuf, dbuf;
417     RECT                rsrc2;
418
419
420     if (TRACE_ON(ddraw)) {
421         FIXME("(%p)->(%ld,%ld,%p,%p,%08lx)\n",
422                 This,dstx,dsty,src,rsrc,trans
423         );
424         FIXME(" trans:");
425         if (FIXME_ON(ddraw))
426           _dump_DDBLTFAST(trans);
427         if (rsrc)
428           FIXME("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
429         else
430           FIXME(" srcrect: NULL\n");
431     }
432     
433     /* We need to lock the surfaces, or we won't get refreshes when done. */
434     IDirectDrawSurface4_Lock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
435     IDirectDrawSurface4_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
436
437    if (!rsrc) {
438            WARN("rsrc is NULL!\n");
439            rsrc = &rsrc2;
440            rsrc->left = rsrc->top = 0;
441            rsrc->right = sdesc.dwWidth;
442            rsrc->bottom = sdesc.dwHeight;
443    }
444
445     bpp = GET_BPP(This->s.surface_desc);
446     sbuf = (BYTE *)sdesc.u1.lpSurface+(rsrc->top*sdesc.lPitch)+rsrc->left*bpp;
447     dbuf = (BYTE *)ddesc.u1.lpSurface+(dsty*ddesc.lPitch)+dstx* bpp;
448
449
450     h=rsrc->bottom-rsrc->top;
451     if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
452     if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
453     if (h<0) h=0;
454
455     w=rsrc->right-rsrc->left;
456     if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
457     if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
458     if (w<0) w=0;
459
460     if (trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) {
461         DWORD keylow, keyhigh;
462         if (trans & DDBLTFAST_SRCCOLORKEY) {
463             keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
464             keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
465         } else {
466             /* I'm not sure if this is correct */
467             FIXME("DDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
468             keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
469             keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
470         }
471
472 #define COPYBOX_COLORKEY(type) { \
473     type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
474     s = (type *) ((BYTE *) sdesc.u1.lpSurface + (rsrc->top * sdesc.lPitch) + rsrc->left * bpp); \
475     d = (type *) ((BYTE *) ddesc.u1.lpSurface + (dsty * ddesc.lPitch) + dstx * bpp); \
476     for (y = 0; y < h; y++) { \
477         for (x = 0; x < w; x++) { \
478             tmp = s[x]; \
479             if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
480         } \
481         (LPBYTE)s += sdesc.lPitch; \
482         (LPBYTE)d += ddesc.lPitch; \
483     } \
484     break; \
485 }
486
487         switch (bpp) {
488         case 1: COPYBOX_COLORKEY(BYTE)
489         case 2: COPYBOX_COLORKEY(WORD)
490         case 4: COPYBOX_COLORKEY(DWORD)
491         default:
492             FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
493             ret = DDERR_UNSUPPORTED;
494             goto error;
495         }
496 #undef COPYBOX_COLORKEY
497     } else {
498         int width = w * bpp;
499
500         for (y = 0; y < h; y++) {
501             memcpy(dbuf, sbuf, width);
502             sbuf += sdesc.lPitch;
503             dbuf += ddesc.lPitch;
504         }
505     }
506 error:
507     IDirectDrawSurface4_Unlock(iface,ddesc.u1.lpSurface);
508     IDirectDrawSurface4_Unlock(src,sdesc.u1.lpSurface);
509     return ret;
510 }
511
512 HRESULT WINAPI IDirectDrawSurface4Impl_BltBatch(
513     LPDIRECTDRAWSURFACE4 iface,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
514 ) {
515     ICOM_THIS(IDirectDrawSurface4Impl,iface);
516     FIXME("(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",This,ddbltbatch,x,y);
517     return DD_OK;
518 }
519
520 HRESULT WINAPI IDirectDrawSurface4Impl_GetCaps(
521     LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS caps
522 ) {
523     ICOM_THIS(IDirectDrawSurface4Impl,iface);
524     TRACE("(%p)->GetCaps(%p)\n",This,caps);
525     caps->dwCaps = DDSCAPS_PALETTE; /* probably more */
526     return DD_OK;
527 }
528
529 HRESULT WINAPI IDirectDrawSurface4Impl_GetSurfaceDesc(
530     LPDIRECTDRAWSURFACE4 iface,LPDDSURFACEDESC ddsd
531 ) { 
532     ICOM_THIS(IDirectDrawSurface4Impl,iface);
533     TRACE("(%p)->GetSurfaceDesc(%p)\n", This,ddsd);
534   
535     /* Simply copy the surface description stored in the object */
536     *ddsd = This->s.surface_desc;
537   
538     if (TRACE_ON(ddraw)) { _dump_surface_desc(ddsd); }
539
540     return DD_OK;
541 }
542
543 ULONG WINAPI IDirectDrawSurface4Impl_AddRef(LPDIRECTDRAWSURFACE4 iface) {
544     ICOM_THIS(IDirectDrawSurface4Impl,iface);
545     TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
546     return ++(This->ref);
547 }
548
549
550 HRESULT WINAPI IDirectDrawSurface4Impl_GetAttachedSurface(
551     LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE4 *lpdsf
552 ) {
553     ICOM_THIS(IDirectDrawSurface4Impl,iface);
554     int i,found = 0,xstart;
555     struct _surface_chain       *chain;
556
557     TRACE("(%p)->GetAttachedSurface(%p,%p)\n", This, lpddsd, lpdsf);
558     if (TRACE_ON(ddraw)) {
559         TRACE(" caps ");_dump_DDSCAPS((void *) &(lpddsd->dwCaps));
560         DPRINTF("\n");
561     }
562     chain = This->s.chain;
563     if (!chain)
564         return DDERR_NOTFOUND;
565
566     for (i=0;i<chain->nrofsurfaces;i++)
567         if (chain->surfaces[i] == This)
568             break;
569
570     xstart = i;
571     for (i=0;i<chain->nrofsurfaces;i++) {
572         if ((SDDSCAPS(chain->surfaces[(xstart+i)%chain->nrofsurfaces])&lpddsd->dwCaps) == lpddsd->dwCaps) {
573 #if 0
574             if (found) /* may not find the same caps twice, (doc) */
575                 return DDERR_INVALIDPARAMS;/*FIXME: correct? */
576 #endif
577             found = (i+1)+xstart;
578         }
579     }
580     if (!found)
581         return DDERR_NOTFOUND;
582     *lpdsf = (LPDIRECTDRAWSURFACE4)chain->surfaces[found-1-xstart];
583     /* FIXME: AddRef? */
584     TRACE("found %p\n",*lpdsf);
585     return DD_OK;
586 }
587
588 HRESULT WINAPI IDirectDrawSurface4Impl_Initialize(
589     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
590 ) {
591     ICOM_THIS(IDirectDrawSurface4Impl,iface);
592     TRACE("(%p)->(%p, %p)\n",This,ddraw,lpdsfd);
593
594     return DDERR_ALREADYINITIALIZED;
595 }
596
597 HRESULT WINAPI IDirectDrawSurface4Impl_GetPixelFormat(
598     LPDIRECTDRAWSURFACE4 iface,LPDDPIXELFORMAT pf
599 ) {
600     ICOM_THIS(IDirectDrawSurface4Impl,iface);
601     TRACE("(%p)->(%p)\n",This,pf);
602
603     *pf = This->s.surface_desc.ddpfPixelFormat;
604     if (TRACE_ON(ddraw)) { _dump_pixelformat(pf); DPRINTF("\n"); }
605     return DD_OK;
606 }
607
608 HRESULT WINAPI IDirectDrawSurface4Impl_GetBltStatus(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags) {
609     ICOM_THIS(IDirectDrawSurface4Impl,iface);
610     FIXME("(%p)->(0x%08lx),stub!\n",This,dwFlags);
611     return DD_OK;
612 }
613
614 HRESULT WINAPI IDirectDrawSurface4Impl_GetOverlayPosition(
615     LPDIRECTDRAWSURFACE4 iface,LPLONG x1,LPLONG x2
616 ) {
617     ICOM_THIS(IDirectDrawSurface4Impl,iface);
618     FIXME("(%p)->(%p,%p),stub!\n",This,x1,x2);
619     return DD_OK;
620 }
621
622 HRESULT WINAPI IDirectDrawSurface4Impl_SetClipper(
623     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWCLIPPER lpClipper
624 ) {
625     ICOM_THIS(IDirectDrawSurface4Impl,iface);
626     TRACE("(%p)->(%p)!\n",This,lpClipper);
627
628     if (This->s.lpClipper) IDirectDrawClipper_Release( This->s.lpClipper );
629     This->s.lpClipper = lpClipper;
630     if (lpClipper) IDirectDrawClipper_AddRef( lpClipper );
631     return DD_OK;
632 }
633
634 HRESULT WINAPI IDirectDrawSurface4Impl_AddAttachedSurface(
635     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 surf
636 ) {
637     ICOM_THIS(IDirectDrawSurface4Impl,iface);
638     IDirectDrawSurface4Impl*isurf = (IDirectDrawSurface4Impl*)surf;
639     int i;
640     struct _surface_chain *chain;
641
642     FIXME("(%p)->(%p)\n",This,surf);
643     chain = This->s.chain;
644
645     /* IDirectDrawSurface4_AddRef(surf); */
646     
647     if (chain) {
648         for (i=0;i<chain->nrofsurfaces;i++)
649             if (chain->surfaces[i] == isurf)
650                 FIXME("attaching already attached surface %p to %p!\n",iface,isurf);
651     } else {
652         chain = HeapAlloc(GetProcessHeap(),0,sizeof(*chain));
653         chain->nrofsurfaces = 1;
654         chain->surfaces = HeapAlloc(GetProcessHeap(),0,sizeof(chain->surfaces[0]));
655         chain->surfaces[0] = This;
656         This->s.chain = chain;
657     }
658
659     if (chain->surfaces)
660         chain->surfaces = HeapReAlloc(
661             GetProcessHeap(),
662             0,
663             chain->surfaces,
664             sizeof(chain->surfaces[0])*(chain->nrofsurfaces+1)
665         );
666     else
667         chain->surfaces = HeapAlloc(GetProcessHeap(),0,sizeof(chain->surfaces[0]));
668     isurf->s.chain = chain;
669     chain->surfaces[chain->nrofsurfaces++] = isurf;
670     return DD_OK;
671 }
672
673 HRESULT WINAPI IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
674     ICOM_THIS(IDirectDrawSurface4Impl,iface);
675     DDSURFACEDESC desc;
676     BITMAPINFO *b_info;
677     UINT usage;
678
679     FIXME("(%p)->GetDC(%p)\n",This,lphdc);
680
681     /* Creates a DIB Section of the same size / format as the surface */
682     IDirectDrawSurface4_Lock(iface,NULL,&desc,0,0);
683
684     if (This->s.hdc == 0) {
685         switch (desc.ddpfPixelFormat.u.dwRGBBitCount) {
686         case 16:
687         case 32:
688 #if 0 /* This should be filled if Wine's DIBSection did understand BI_BITFIELDS */
689             b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
690             break;
691 #endif
692
693         case 24:
694             b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
695             break;
696
697         default:
698             b_info = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
699                     sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (2 << desc.ddpfPixelFormat.u.dwRGBBitCount));
700             break;
701         }
702
703         b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
704         b_info->bmiHeader.biWidth = desc.dwWidth;
705         b_info->bmiHeader.biHeight = desc.dwHeight;
706         b_info->bmiHeader.biPlanes = 1;
707         b_info->bmiHeader.biBitCount = desc.ddpfPixelFormat.u.dwRGBBitCount;
708 #if 0
709         if ((desc.ddpfPixelFormat.u.dwRGBBitCount != 16) &&
710             (desc.ddpfPixelFormat.u.dwRGBBitCount != 32))
711 #endif
712         b_info->bmiHeader.biCompression = BI_RGB;
713 #if 0
714         else
715         b_info->bmiHeader.biCompression = BI_BITFIELDS;
716 #endif
717         b_info->bmiHeader.biSizeImage = (desc.ddpfPixelFormat.u.dwRGBBitCount / 8) * desc.dwWidth * desc.dwHeight;
718         b_info->bmiHeader.biXPelsPerMeter = 0;
719         b_info->bmiHeader.biYPelsPerMeter = 0;
720         b_info->bmiHeader.biClrUsed = 0;
721         b_info->bmiHeader.biClrImportant = 0;
722
723         switch (desc.ddpfPixelFormat.u.dwRGBBitCount) {
724         case 16:
725         case 32:
726 #if 0
727             {
728                 DWORD *masks = (DWORD *) &(b_info->bmiColors);
729
730                 usage = 0;
731                 masks[0] = desc.ddpfPixelFormat.u1.dwRBitMask;
732                 masks[1] = desc.ddpfPixelFormat.u2.dwGBitMask;
733                 masks[2] = desc.ddpfPixelFormat.u3.dwBBitMask;
734             }
735             break;
736 #endif
737         case 24:
738             /* Nothing to do */
739             usage = DIB_RGB_COLORS;
740             break;
741
742         default: {
743                 int i;
744
745                 /* Fill the palette */
746                 usage = DIB_RGB_COLORS;
747
748                 if (This->s.palette == NULL) {
749                     ERR("Bad palette !!!\n");
750                 } else {
751                     RGBQUAD *rgb = (RGBQUAD *) &(b_info->bmiColors);
752                     PALETTEENTRY *pent = (PALETTEENTRY *)&(This->s.palette->palents);
753
754                     for (i=0;i<(1<<desc.ddpfPixelFormat.u.dwRGBBitCount);i++) {
755                         rgb[i].rgbBlue = pent[i].peBlue;
756                         rgb[i].rgbRed = pent[i].peRed;
757                         rgb[i].rgbGreen = pent[i].peGreen; 
758                     }
759                 }
760             }
761             break;
762         }
763         This->s.DIBsection = CreateDIBSection(BeginPaint(This->s.ddraw->d.mainWindow,&This->s.ddraw->d.ps),
764             b_info,
765             usage,
766             &(This->s.bitmap_data),
767             0,
768             0
769         );
770         EndPaint(This->s.ddraw->d.mainWindow,&This->s.ddraw->d.ps);
771         if (!This->s.DIBsection) {
772                 ERR("CreateDIBSection failed!\n");
773                 return E_FAIL;
774         }
775         TRACE("DIBSection at : %p\n", This->s.bitmap_data);
776
777         /* b_info is not useful anymore */
778         HeapFree(GetProcessHeap(), 0, b_info);
779
780         /* Create the DC */
781         This->s.hdc = CreateCompatibleDC(0);
782         This->s.holdbitmap = SelectObject(This->s.hdc, This->s.DIBsection);
783     }
784
785     /* Copy our surface in the DIB section */
786     if ((GET_BPP(desc) * desc.dwWidth) == desc.lPitch)
787         memcpy(This->s.bitmap_data,desc.u1.lpSurface,desc.lPitch*desc.dwHeight);
788     else
789         /* TODO */
790         FIXME("This case has to be done :/\n");
791
792     TRACE("HDC : %08lx\n", (DWORD) This->s.hdc);
793     *lphdc = This->s.hdc;
794
795     return DD_OK;
796 }
797
798 HRESULT WINAPI IDirectDrawSurface4Impl_ReleaseDC(LPDIRECTDRAWSURFACE4 iface,HDC hdc) {
799     ICOM_THIS(IDirectDrawSurface4Impl,iface);
800
801     FIXME("(%p)->(0x%08lx),stub!\n",This,(long)hdc);
802     TRACE( "Copying DIBSection at : %p\n", This->s.bitmap_data);
803     /* Copy the DIB section to our surface */
804     if ((GET_BPP(This->s.surface_desc) * This->s.surface_desc.dwWidth) == This->s.surface_desc.lPitch) {
805         memcpy(This->s.surface_desc.u1.lpSurface, This->s.bitmap_data, This->s.surface_desc.lPitch * This->s.surface_desc.dwHeight);
806     } else {
807         /* TODO */
808         FIXME("This case has to be done :/\n");
809     }
810     /* Unlock the surface */
811     IDirectDrawSurface4_Unlock(iface,This->s.surface_desc.u1.lpSurface);
812     return DD_OK;
813 }
814
815 HRESULT WINAPI IDirectDrawSurface4Impl_QueryInterface(
816     LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
817 ) {
818     ICOM_THIS(IDirectDrawSurface4Impl,iface);
819
820     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
821     
822     /* All DirectDrawSurface versions (1, 2, 3 and 4) use
823      * the same interface. And IUnknown does that too of course.
824      */
825     if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid )        ||
826          IsEqualGUID( &IID_IDirectDrawSurface3, refiid )        ||
827          IsEqualGUID( &IID_IDirectDrawSurface2, refiid )        ||
828          IsEqualGUID( &IID_IDirectDrawSurface,  refiid )        ||
829          IsEqualGUID( &IID_IUnknown,            refiid )
830     ) {
831             *obj = This;
832             IDirectDrawSurface4_AddRef(iface);
833
834             TRACE("  Creating IDirectDrawSurface interface (%p)\n", *obj);
835             return S_OK;
836     }
837     FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
838     return OLE_E_ENUM_NOMORE;
839 }
840
841 HRESULT WINAPI IDirectDrawSurface4Impl_IsLost(LPDIRECTDRAWSURFACE4 iface) {
842     ICOM_THIS(IDirectDrawSurface4Impl,iface);
843     TRACE("(%p)->(), stub!\n",This);
844     return DD_OK; /* hmm */
845 }
846
847 HRESULT WINAPI IDirectDrawSurface4Impl_EnumAttachedSurfaces(
848     LPDIRECTDRAWSURFACE4 iface,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb
849 ) {
850     ICOM_THIS(IDirectDrawSurface4Impl,iface);
851     int i;
852     struct _surface_chain *chain = This->s.chain;
853
854     TRACE("(%p)->(%p,%p)\n",This,context,esfcb);
855     for (i=0;i<chain->nrofsurfaces;i++) {
856       TRACE( "Enumerating attached surface (%p)\n", chain->surfaces[i]);
857       if (esfcb((LPDIRECTDRAWSURFACE) chain->surfaces[i], &(chain->surfaces[i]->s.surface_desc), context) == DDENUMRET_CANCEL)
858         return DD_OK; /* FIXME: return value correct? */
859     }
860     return DD_OK;
861 }
862
863 HRESULT WINAPI IDirectDrawSurface4Impl_Restore(LPDIRECTDRAWSURFACE4 iface) {
864     ICOM_THIS(IDirectDrawSurface4Impl,iface);
865     FIXME("(%p)->(),stub!\n",This);
866     return DD_OK;
867 }
868
869 HRESULT WINAPI IDirectDrawSurface4Impl_SetColorKey(
870     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY ckey ) 
871 {
872     ICOM_THIS(IDirectDrawSurface4Impl,iface);
873     TRACE("(%p)->(0x%08lx,%p)\n",This,dwFlags,ckey);
874     if (TRACE_ON(ddraw)) {
875         _dump_colorkeyflag(dwFlags);
876         DPRINTF(" : ");
877         _dump_DDCOLORKEY((void *) ckey);
878         DPRINTF("\n");
879     }
880
881     /* If this surface was loaded as a texture, call also the texture
882      * SetColorKey callback. FIXME: hack approach :(
883      */
884     if (This->s.texture)
885         This->s.SetColorKey_cb(This->s.texture, dwFlags, ckey);
886
887     if( dwFlags & DDCKEY_SRCBLT ) {
888         dwFlags &= ~DDCKEY_SRCBLT;
889         This->s.surface_desc.dwFlags |= DDSD_CKSRCBLT;
890         memcpy( &(This->s.surface_desc.ddckCKSrcBlt), ckey, sizeof( *ckey ) );
891     }
892
893     if( dwFlags & DDCKEY_DESTBLT ) {
894         dwFlags &= ~DDCKEY_DESTBLT;
895         This->s.surface_desc.dwFlags |= DDSD_CKDESTBLT;
896         memcpy( &(This->s.surface_desc.ddckCKDestBlt), ckey, sizeof( *ckey ) );
897     }
898
899     if( dwFlags & DDCKEY_SRCOVERLAY ) {
900         dwFlags &= ~DDCKEY_SRCOVERLAY;
901         This->s.surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
902         memcpy( &(This->s.surface_desc.ddckCKSrcOverlay), ckey, sizeof( *ckey ) );         
903     }
904
905     if( dwFlags & DDCKEY_DESTOVERLAY ) {
906         dwFlags &= ~DDCKEY_DESTOVERLAY;
907         This->s.surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
908         memcpy( &(This->s.surface_desc.ddckCKDestOverlay), ckey, sizeof( *ckey ) );        
909     }
910     if( dwFlags )
911         FIXME("unhandled dwFlags: 0x%08lx\n", dwFlags );
912     return DD_OK;
913 }
914
915 HRESULT WINAPI IDirectDrawSurface4Impl_AddOverlayDirtyRect(
916     LPDIRECTDRAWSURFACE4 iface, LPRECT lpRect
917 ) {
918   ICOM_THIS(IDirectDrawSurface4Impl,iface);
919   FIXME("(%p)->(%p),stub!\n",This,lpRect); 
920
921   return DD_OK;
922 }
923
924 HRESULT WINAPI IDirectDrawSurface4Impl_DeleteAttachedSurface(
925     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags,
926     LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface
927 ) {
928     ICOM_THIS(IDirectDrawSurface4Impl,iface);
929     int i;
930     struct _surface_chain *chain;
931
932     TRACE("(%p)->(0x%08lx,%p)\n",This,dwFlags,lpDDSAttachedSurface);
933     chain = This->s.chain;
934     for (i=0;i<chain->nrofsurfaces;i++) {
935         if ((IDirectDrawSurface4Impl*)lpDDSAttachedSurface==chain->surfaces[i]){
936             IDirectDrawSurface4_Release(lpDDSAttachedSurface);
937
938             chain->surfaces[i]->s.chain = NULL;
939             memcpy( chain->surfaces+i,
940                     chain->surfaces+(i+1),
941                     (chain->nrofsurfaces-i-1)*sizeof(chain->surfaces[i])
942             );
943             chain->surfaces = HeapReAlloc(
944                 GetProcessHeap(),
945                 0,
946                 chain->surfaces,
947                 sizeof(chain->surfaces[i])*(chain->nrofsurfaces-1)
948             );
949             chain->nrofsurfaces--;
950             return DD_OK;
951         }
952     }
953     return DD_OK;
954 }
955
956 HRESULT WINAPI IDirectDrawSurface4Impl_EnumOverlayZOrders(
957     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPVOID lpContext,
958     LPDDENUMSURFACESCALLBACK lpfnCallback
959 ) {
960   ICOM_THIS(IDirectDrawSurface4Impl,iface);
961   FIXME("(%p)->(0x%08lx,%p,%p),stub!\n", This,dwFlags,
962           lpContext, lpfnCallback );
963
964   return DD_OK;
965 }
966
967 HRESULT WINAPI IDirectDrawSurface4Impl_GetClipper(
968     LPDIRECTDRAWSURFACE4 iface, LPDIRECTDRAWCLIPPER* lplpDDClipper
969 ) {
970   ICOM_THIS(IDirectDrawSurface4Impl,iface);
971   FIXME("(%p)->(%p),stub!\n", This, lplpDDClipper);
972
973   return DD_OK;
974 }
975
976 HRESULT WINAPI IDirectDrawSurface4Impl_GetColorKey(
977     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY lpDDColorKey
978 ) {
979     ICOM_THIS(IDirectDrawSurface4Impl,iface);
980     TRACE("(%p)->(0x%08lx,%p)\n", This, dwFlags, lpDDColorKey);
981
982     if( dwFlags & DDCKEY_SRCBLT )  {
983         dwFlags &= ~DDCKEY_SRCBLT;
984         memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcBlt), sizeof( *lpDDColorKey ) );
985     }
986     if( dwFlags & DDCKEY_DESTBLT ) {
987         dwFlags &= ~DDCKEY_DESTBLT;
988         memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestBlt), sizeof( *lpDDColorKey ) );
989     }
990     if( dwFlags & DDCKEY_SRCOVERLAY ) {
991         dwFlags &= ~DDCKEY_SRCOVERLAY;
992         memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcOverlay), sizeof( *lpDDColorKey ) );
993     }
994     if( dwFlags & DDCKEY_DESTOVERLAY ) {
995         dwFlags &= ~DDCKEY_DESTOVERLAY;
996         memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestOverlay), sizeof( *lpDDColorKey ) );
997     }
998     if( dwFlags )
999         FIXME("unhandled dwFlags: 0x%08lx\n", dwFlags );
1000     return DD_OK;
1001 }
1002
1003 HRESULT WINAPI IDirectDrawSurface4Impl_GetFlipStatus(
1004     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
1005 ) {
1006     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1007     FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
1008
1009     return DD_OK;
1010 }
1011
1012 HRESULT WINAPI IDirectDrawSurface4Impl_GetPalette(
1013     LPDIRECTDRAWSURFACE4 iface, LPDIRECTDRAWPALETTE* lplpDDPalette
1014 ) {
1015     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1016     TRACE("(%p)->(%p),stub!\n", This, lplpDDPalette);
1017
1018     if (!This->s.palette)
1019         return DDERR_NOPALETTEATTACHED;
1020
1021     IDirectDrawPalette_AddRef( (IDirectDrawPalette*) This->s.palette );
1022     *lplpDDPalette = (IDirectDrawPalette*) This->s.palette;
1023     return DD_OK;
1024 }
1025
1026 HRESULT WINAPI IDirectDrawSurface4Impl_SetOverlayPosition(
1027     LPDIRECTDRAWSURFACE4 iface, LONG lX, LONG lY
1028 ) {
1029     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1030     FIXME("(%p)->(%ld,%ld),stub!\n", This, lX, lY);
1031
1032     return DD_OK;
1033 }
1034
1035 HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlay(
1036     LPDIRECTDRAWSURFACE4 iface, LPRECT lpSrcRect,
1037     LPDIRECTDRAWSURFACE4 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags,
1038     LPDDOVERLAYFX lpDDOverlayFx
1039 ) {
1040     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1041     FIXME("(%p)->(%p,%p,%p,0x%08lx,%p),stub!\n", This,
1042          lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );  
1043
1044     return DD_OK;
1045 }
1046  
1047 HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayDisplay(
1048     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
1049 ) {
1050     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1051     FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags); 
1052
1053     return DD_OK;
1054 }
1055
1056 HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayZOrder(
1057     LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags,LPDIRECTDRAWSURFACE4 lpDDSReference
1058 ) {
1059     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1060     FIXME("(%p)->(0x%08lx,%p),stub!\n", This, dwFlags, lpDDSReference);
1061
1062     return DD_OK;
1063 }
1064
1065 HRESULT WINAPI IDirectDrawSurface4Impl_GetDDInterface(
1066     LPDIRECTDRAWSURFACE4 iface, LPVOID* lplpDD
1067 ) {
1068     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1069     FIXME("(%p)->(%p),stub!\n", This, lplpDD);
1070
1071     /* Not sure about that... */
1072     *lplpDD = (void *) This->s.ddraw;
1073
1074     return DD_OK;
1075 }
1076
1077 HRESULT WINAPI IDirectDrawSurface4Impl_PageLock(
1078     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
1079 ) {
1080     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1081     FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
1082
1083     return DD_OK;
1084 }
1085
1086 HRESULT WINAPI IDirectDrawSurface4Impl_PageUnlock(
1087     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
1088 ) {
1089     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1090     FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
1091
1092     return DD_OK;
1093 }
1094
1095 HRESULT WINAPI IDirectDrawSurface4Impl_SetSurfaceDesc(
1096     LPDIRECTDRAWSURFACE4 iface, LPDDSURFACEDESC lpDDSD, DWORD dwFlags
1097 ) {
1098     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1099     FIXME("(%p)->(%p,0x%08lx),stub!\n", This, lpDDSD, dwFlags);
1100
1101     return DD_OK;
1102 }
1103
1104 HRESULT WINAPI IDirectDrawSurface4Impl_SetPrivateData(
1105     LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag, LPVOID lpData, DWORD cbSize,
1106     DWORD dwFlags
1107 ) {
1108     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1109     FIXME("(%p)->(%p,%p,%ld,%08lx\n", This, guidTag, lpData, cbSize, dwFlags);
1110
1111     return DD_OK;
1112 }
1113
1114 HRESULT WINAPI IDirectDrawSurface4Impl_GetPrivateData(
1115     LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag, LPVOID lpBuffer,
1116     LPDWORD lpcbBufferSize
1117 ) {
1118     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1119     FIXME("(%p)->(%p,%p,%p)\n", This, guidTag, lpBuffer, lpcbBufferSize);
1120
1121     return DD_OK;
1122 }
1123
1124 HRESULT WINAPI IDirectDrawSurface4Impl_FreePrivateData(
1125     LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag
1126 ) {
1127     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1128     FIXME("(%p)->(%p)\n", This, guidTag);
1129
1130     return DD_OK;
1131 }
1132
1133 HRESULT WINAPI IDirectDrawSurface4Impl_GetUniquenessValue(
1134     LPDIRECTDRAWSURFACE4 iface, LPDWORD lpValue
1135 )  {
1136     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1137     FIXME("(%p)->(%p)\n", This, lpValue);
1138
1139     return DD_OK;
1140 }
1141
1142 HRESULT WINAPI IDirectDrawSurface4Impl_ChangeUniquenessValue(
1143     LPDIRECTDRAWSURFACE4 iface
1144 ) {
1145     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1146     FIXME("(%p)\n", This);
1147
1148     return DD_OK;
1149 }