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