Assorted spelling fixes.
[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  * Copyright 2000-2001 TransGaming Technologies Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include "config.h"
22
23 #include <assert.h>
24 #include <string.h>
25
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "winerror.h"
29 #include "mesa_private.h"
30 #include "wine/debug.h"
31 #include "ddraw_private.h"
32 #include "dsurface/main.h"
33 #include "ddraw/main.h"
34 #include "dsurface/thunks.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 WINE_DECLARE_DEBUG_CHANNEL(ddraw_flip);
38
39 /** Creation/Destruction functions */
40
41 HRESULT
42 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
43                                  IDirectDrawImpl *pDD,
44                                  const DDSURFACEDESC2 *pDDSD)
45 {
46     TRACE("(%p)->(%p,%p)\n", This, pDD, pDDSD);
47
48     if (pDDSD != &This->surface_desc) {
49         This->surface_desc.dwSize = sizeof(This->surface_desc);
50         DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
51     }
52     This->uniqueness_value = 1; /* unchecked */
53     This->ref = 1;
54
55     This->local.lpSurfMore = &This->more;
56     This->local.lpGbl = &This->global;
57     This->local.dwProcessId = GetCurrentProcessId();
58     This->local.dwFlags = 0; /* FIXME */
59     This->local.ddsCaps.dwCaps = This->surface_desc.ddsCaps.dwCaps;
60     /* FIXME: more local stuff */
61     This->more.lpDD_lcl = &pDD->local;
62     This->more.ddsCapsEx.dwCaps2 = This->surface_desc.ddsCaps.dwCaps2;
63     This->more.ddsCapsEx.dwCaps3 = This->surface_desc.ddsCaps.dwCaps3;
64     This->more.ddsCapsEx.dwCaps4 = This->surface_desc.ddsCaps.dwCaps4;
65     /* FIXME: more more stuff */
66     This->gmore = &This->global_more;
67     This->global.u3.lpDD = pDD->local.lpGbl;
68     /* FIXME: more global stuff */
69
70     This->final_release = Main_DirectDrawSurface_final_release;
71     This->late_allocate = Main_DirectDrawSurface_late_allocate;
72     This->attach = Main_DirectDrawSurface_attach;
73     This->detach = Main_DirectDrawSurface_detach;
74     This->lock_update = Main_DirectDrawSurface_lock_update;
75     This->unlock_update = Main_DirectDrawSurface_unlock_update;
76     This->lose_surface = Main_DirectDrawSurface_lose_surface;
77     This->set_palette    = Main_DirectDrawSurface_set_palette;
78     This->update_palette = Main_DirectDrawSurface_update_palette;
79     This->get_display_window = Main_DirectDrawSurface_get_display_window;
80     This->get_gamma_ramp = Main_DirectDrawSurface_get_gamma_ramp;
81     This->set_gamma_ramp = Main_DirectDrawSurface_set_gamma_ramp;
82
83     ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
84                         DDRAW_IDDS3_Thunk_VTable);
85     ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
86                         DDRAW_IDDGC_VTable);
87
88     /* There is no generic implementation of IDDS7 or texture */
89
90     Main_DirectDraw_AddSurface(pDD, This);
91     return DD_OK;
92 }
93
94 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
95 {
96     Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
97 }
98
99 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
100 {
101     return DD_OK;
102 }
103
104 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
105 {
106     if (This->palette) {
107         IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette, IDirectDrawPalette));
108         This->palette = NULL;
109     }
110     This->final_release(This);
111     if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
112     if (This->tex_private) HeapFree(GetProcessHeap(), 0, This->tex_private);
113     HeapFree(GetProcessHeap(), 0, This);
114 }
115
116 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
117 {
118     WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
119     Main_DirectDrawSurface_Destroy(This);
120 }
121
122 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
123 {
124     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
125
126     TRACE("(%p)->(): decreasing from %ld\n", This, This->ref);
127     
128     if (--This->ref == 0)
129     {
130         if (This->aux_release)
131             This->aux_release(This->aux_ctx, This->aux_data);
132         Main_DirectDrawSurface_Destroy(This);
133
134         TRACE("released surface %p\n", This);
135         
136         return 0;
137     }
138
139     return This->ref;
140 }
141
142 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
143 {
144     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
145
146     TRACE("(%p)->(): increasing from %ld\n", This, This->ref);
147     
148     return ++This->ref;
149 }
150
151 HRESULT WINAPI
152 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
153                                       LPVOID* ppObj)
154 {
155     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
156     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
157
158     *ppObj = NULL;
159
160     if (IsEqualGUID(&IID_IUnknown, riid)
161         || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
162         || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
163     {
164         This->ref++;
165         *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
166         return S_OK;
167     }
168     else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
169              || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
170              || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
171     {
172         This->ref++;
173         *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
174         return S_OK;
175     }
176     else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
177     {
178         This->ref++;
179         *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
180         return S_OK;
181     }
182 #ifdef HAVE_OPENGL
183     /* interfaces following here require OpenGL */
184     if( !opengl_initialized )
185         return E_NOINTERFACE;
186
187     if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL, riid ) ||
188           IsEqualGUID( &IID_IDirect3DHALDevice, riid) )
189     {
190         IDirect3DDeviceImpl *d3ddevimpl;
191         HRESULT ret_value;
192
193         ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, TRUE);
194         if (FAILED(ret_value)) return ret_value;
195
196         *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
197         TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj);
198         
199         This->ref++; /* No idea if this is correct.. Need to check using real Windows */
200         return ret_value;
201     }
202     else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
203              IsEqualGUID( &IID_IDirect3DTexture2, riid ))
204     {
205         HRESULT ret_value = S_OK;
206
207         /* Note: this is not exactly how Windows does it... But this seems not to hurt the only
208                  application I know creating a texture without this flag set and it will prevent
209                  bugs in other parts of Wine.
210         */
211         This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
212
213         /* In case the texture surface was created before the D3D creation */
214         if (This->tex_private == NULL) {
215             if (This->ddraw_owner->d3d_private == NULL) {
216                 ERR("Texture created with no D3D object yet.. Not supported !\n");
217                 return E_NOINTERFACE;
218             }
219
220             ret_value = This->ddraw_owner->d3d_create_texture(This->ddraw_owner, This, FALSE, This->mip_main);
221             if (FAILED(ret_value)) return ret_value;
222         }
223         if (IsEqualGUID( &IID_IDirect3DTexture, riid )) {
224             *ppObj = ICOM_INTERFACE(This, IDirect3DTexture);
225             TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj);
226         } else {
227             *ppObj = ICOM_INTERFACE(This, IDirect3DTexture2);
228             TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj);
229         }
230         This->ref++;
231         return ret_value;
232     }
233 #endif
234
235     return E_NOINTERFACE;
236 }
237
238 /*** Callbacks */
239
240 BOOL
241 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
242                               IDirectDrawSurfaceImpl *to)
243 {
244     return TRUE;
245 }
246
247 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
248 {
249     return TRUE;
250 }
251
252 void
253 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
254         DWORD dwFlags)
255 {
256 }
257
258 void
259 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
260                                      LPCRECT pRect)
261 {
262 }
263
264 void
265 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
266 {
267 }
268
269 void
270 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
271                                    IDirectDrawPaletteImpl* pal)
272 {
273 }
274
275 void
276 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
277                                       IDirectDrawPaletteImpl* pal,
278                                       DWORD dwStart, DWORD dwCount,
279                                       LPPALETTEENTRY palent)
280 {
281 }
282
283 HWND
284 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
285 {
286     return 0;
287 }
288
289 HRESULT
290 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
291                                       DWORD dwFlags,
292                                       LPDDGAMMARAMP lpGammaRamp)
293 {
294     HDC hDC;
295     HRESULT hr;
296     hr = This->get_dc(This, &hDC);
297     if (FAILED(hr)) return hr;
298     hr = GetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
299     This->release_dc(This, hDC);
300     return hr;
301 }
302
303 HRESULT
304 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
305                                       DWORD dwFlags,
306                                       LPDDGAMMARAMP lpGammaRamp)
307 {
308     HDC hDC;
309     HRESULT hr;
310     hr = This->get_dc(This, &hDC);
311     if (FAILED(hr)) return hr;
312     hr = SetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
313     This->release_dc(This, hDC);
314     return hr;
315 }
316
317
318 /*** Interface functions */
319
320 HRESULT WINAPI
321 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
322                                           LPDIRECTDRAWSURFACE7 pAttach)
323 {
324     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
325     IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
326                                                IDirectDrawSurface7, pAttach);
327
328     TRACE("(%p)->(%p)\n",This,pAttach);
329
330     /* Does windows check this? */
331     if (surf == This)
332         return DDERR_CANNOTATTACHSURFACE; /* unchecked */
333
334     /* Does windows check this? */
335     if (surf->ddraw_owner != This->ddraw_owner)
336         return DDERR_CANNOTATTACHSURFACE; /* unchecked */
337
338     if (surf->surface_owner != NULL)
339         return DDERR_SURFACEALREADYATTACHED; /* unchecked */
340
341     /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
342      * But apparently backbuffers and mipmaps can be attached too. */
343
344     /* Set MIPMAPSUBLEVEL if this seems to be one */
345     if (This->surface_desc.ddsCaps.dwCaps &
346         surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
347         surf->surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
348         /* FIXME: we should probably also add to dwMipMapCount of this
349          * and all parent surfaces (update create_texture if you do) */
350     }
351
352     /* Callback to allow the surface to do something special now that it is
353      * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
354     if (!surf->attach(surf, This))
355         return DDERR_CANNOTATTACHSURFACE;
356
357     /* check: Where should it go in the chain? This puts it on the head. */
358     if (This->attached)
359         This->attached->prev_attached = surf;
360     surf->next_attached = This->attached;
361     surf->prev_attached = NULL;
362     This->attached = surf;
363     surf->surface_owner = This;
364
365     IDirectDrawSurface7_AddRef(pAttach);
366
367     return DD_OK;
368 }
369
370 /* MSDN: "not currently implemented." */
371 HRESULT WINAPI
372 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
373                                            LPRECT pRect)
374 {
375     TRACE("(%p)->(%p)\n",iface,pRect);
376     return DDERR_UNSUPPORTED; /* unchecked */
377 }
378
379 /* MSDN: "not currently implemented." */
380 HRESULT WINAPI
381 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
382                                 LPDDBLTBATCH pBatch, DWORD dwCount,
383                                 DWORD dwFlags)
384 {
385     TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
386     return DDERR_UNSUPPORTED; /* unchecked */
387 }
388
389 HRESULT WINAPI
390 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
391 {
392     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
393     volatile IDirectDrawSurfaceImpl* vThis = This;
394
395     TRACE("(%p)\n",This);
396     /* A uniquness value of 0 is apparently special.
397      * This needs to be checked. */
398     while (1)
399     {
400         DWORD old_uniqueness_value = vThis->uniqueness_value;
401         DWORD new_uniqueness_value = old_uniqueness_value+1;
402
403         if (old_uniqueness_value == 0) break;
404         if (new_uniqueness_value == 0) new_uniqueness_value = 1;
405
406         if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
407                                        old_uniqueness_value,
408                                        new_uniqueness_value)
409             == old_uniqueness_value)
410             break;
411     }
412
413     return DD_OK;
414 }
415
416 HRESULT WINAPI
417 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
418                                              DWORD dwFlags,
419                                              LPDIRECTDRAWSURFACE7 pAttach)
420 {
421     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
422     IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
423                                                IDirectDrawSurface7, pAttach);
424
425     TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
426
427     if (!surf || (surf->surface_owner != This))
428         return DDERR_SURFACENOTATTACHED; /* unchecked */
429
430     surf->detach(surf);
431
432     /* Remove MIPMAPSUBLEVEL if this seemed to be one */
433     if (This->surface_desc.ddsCaps.dwCaps &
434         surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
435         surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
436         /* FIXME: we should probably also subtract from dwMipMapCount of this
437          * and all parent surfaces */
438     }
439
440     if (surf->next_attached)
441         surf->next_attached->prev_attached = surf->prev_attached;
442     if (surf->prev_attached)
443         surf->prev_attached->next_attached = surf->next_attached;
444     if (This->attached == surf)
445         This->attached = surf->next_attached;
446
447     IDirectDrawSurface7_Release(pAttach);
448
449     return DD_OK;
450 }
451
452 HRESULT WINAPI
453 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
454                                             LPVOID context,
455                                             LPDDENUMSURFACESCALLBACK7 cb)
456 {
457     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
458     IDirectDrawSurfaceImpl* surf;
459
460     TRACE("(%p)->(%p,%p)\n",This,context,cb);
461
462     for (surf = This->attached; surf != NULL; surf = surf->next_attached)
463     {
464         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
465         if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
466                context) == DDENUMRET_CANCEL)
467             break;
468     }
469
470     return DD_OK;
471 }
472
473 HRESULT WINAPI
474 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
475                                           DWORD dwFlags, LPVOID context,
476                                           LPDDENUMSURFACESCALLBACK7 cb)
477 {
478     TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
479     return DD_OK;
480 }
481
482 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
483                                       IDirectDrawSurfaceImpl* back,
484                                       DWORD dwFlags)
485 {
486     /* uniqueness_value? */
487     /* This is necessary. But is it safe? */
488     {
489         HDC tmp = front->hDC;
490         front->hDC = back->hDC;
491         back->hDC = tmp;
492     }
493
494     {
495         BOOL tmp = front->dc_in_use;
496         front->dc_in_use = back->dc_in_use;
497         back->dc_in_use = tmp;
498     }
499
500     {
501         FLATPTR tmp = front->global.fpVidMem;
502         front->global.fpVidMem = back->global.fpVidMem;
503         back->global.fpVidMem = tmp;
504     }
505
506     {
507         ULONG_PTR tmp = front->global_more.hKernelSurface;
508         front->global_more.hKernelSurface = back->global_more.hKernelSurface;
509         back->global_more.hKernelSurface = tmp;
510     }
511
512     return TRUE;
513 }
514
515 HRESULT WINAPI
516 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
517                             LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
518 {
519     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
520     IDirectDrawSurfaceImpl* target;
521     HRESULT hr;
522
523     TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
524
525     /* MSDN: "This method can be called only for a surface that has the
526      * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
527     if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
528         != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
529         return DDERR_NOTFLIPPABLE;
530
531     if (This->aux_flip)
532         if (This->aux_flip(This->aux_ctx, This->aux_data))
533             return DD_OK;
534
535     /* 1. find the flip target */
536     /* XXX I don't think this algorithm works for more than 1 backbuffer. */
537     if (override == NULL)
538     {
539         static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
540         LPDIRECTDRAWSURFACE7 tgt;
541
542         hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
543         if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
544
545         target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
546                              tgt);
547         IDirectDrawSurface7_Release(tgt);
548     }
549     else
550     {
551         BOOL on_chain = FALSE;
552         IDirectDrawSurfaceImpl* surf;
553
554         /* MSDN: "The method fails if the specified [override] surface is not
555          * a member of the flipping chain." */
556
557         /* Verify that override is on this flip chain. We assume that
558          * surf is the head of the flipping chain, because it's the front
559          * buffer. */
560         target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
561                              override);
562
563         /* Either target is (indirectly) attached to This or This is
564          * (indirectly) attached to target. */
565         for (surf = target; surf != NULL; surf = surf->surface_owner)
566         {
567             if (surf == This)
568             {
569                 on_chain = TRUE;
570                 break;
571             }
572         }
573
574         if (!on_chain)
575             return DDERR_INVALIDPARAMS; /* unchecked */
576     }
577
578     TRACE("flip to backbuffer: %p\n",target);
579     if (TRACE_ON(ddraw_flip)) {
580         static unsigned int flip_count = 0;
581         IDirectDrawPaletteImpl *palette;
582         char buf[32];
583         FILE *f;
584
585         /* Hack for paletted games... */
586         palette = target->palette;
587         target->palette = This->palette;
588         
589         sprintf(buf, "flip_%08d.ppm", flip_count++);
590         TRACE_(ddraw_flip)("Dumping file %s to disk.\n", buf);
591         f = fopen(buf, "wb");
592         DDRAW_dump_surface_to_disk(target, f, 8);
593         target->palette = palette;
594     }
595
596     if (This->flip_data(This, target, dwFlags))
597         This->flip_update(This, dwFlags);
598     
599     return DD_OK;
600 }
601
602 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
603                                       REFGUID tag)
604 {
605     PrivateData* data;
606     for (data = This->private_data; data != NULL; data = data->next)
607     {
608         if (IsEqualGUID(&data->tag, tag)) break;
609     }
610
611     return data;
612 }
613
614 HRESULT WINAPI
615 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
616 {
617     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
618     PrivateData *data;
619
620     data = find_private_data(This, tag);
621     if (data == NULL) return DDERR_NOTFOUND;
622
623     if (data->prev)
624         data->prev->next = data->next;
625     if (data->next)
626         data->next->prev = data->prev;
627
628     if (data->flags & DDSPD_IUNKNOWNPTR)
629     {
630         if (data->ptr.object != NULL)
631             IUnknown_Release(data->ptr.object);
632     }
633     else
634         HeapFree(GetProcessHeap(), 0, data->ptr.data);
635
636     HeapFree(GetProcessHeap(), 0, data);
637
638     return DD_OK;
639 }
640
641 HRESULT WINAPI
642 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
643                                           LPDDSCAPS2 pCaps,
644                                           LPDIRECTDRAWSURFACE7* ppSurface)
645 {
646     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
647     IDirectDrawSurfaceImpl* surf;
648     IDirectDrawSurfaceImpl* found = NULL;
649     DDSCAPS2 our_caps;
650     
651     if (TRACE_ON(ddraw)) {
652         TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
653               pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
654         TRACE("   Caps are : "); DDRAW_dump_DDSCAPS2(pCaps); TRACE("\n");
655     }
656
657     our_caps = *pCaps;
658     if ((This->ddraw_owner->local.dwLocalFlags & DDRAWILCL_DIRECTDRAW7) == 0) {
659         /* As this is not a DirectDraw7 application, remove the garbage that some games
660            put in the new fields of the DDSCAPS2 structure. */
661         our_caps.dwCaps2 = 0;
662         our_caps.dwCaps3 = 0;
663         our_caps.dwCaps4 = 0;
664         if (TRACE_ON(ddraw)) {
665             TRACE("   Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps); TRACE("\n");
666         }
667     }
668     
669     for (surf = This->attached; surf != NULL; surf = surf->next_attached)
670     {
671         if (TRACE_ON(ddraw)) {
672             TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
673                   surf->surface_desc.ddsCaps.dwCaps,
674                   surf->surface_desc.ddsCaps.dwCaps2,
675                   surf->surface_desc.ddsCaps.dwCaps3,
676                   surf->surface_desc.ddsCaps.dwCaps4);
677             TRACE("   Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf->surface_desc.ddsCaps)); TRACE("\n");
678         }
679         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
680             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2))
681         {
682             /* MSDN: "This method fails if more than one surface is attached
683              * that matches the capabilities requested." */
684             if (found != NULL)
685             {
686                 FIXME("More than one attached surface matches requested caps.  What should we do here?\n");
687                 /* Previous code returned 'DDERR_NOTFOUND'.  That appears not
688                    to be correct, given what 3DMark expects from MipMapped surfaces.
689                    We shall just continue instead. */
690             }
691
692             found = surf;
693         }
694     }
695
696     if (found == NULL) {
697         TRACE("Did not find any valid surface\n");
698         return DDERR_NOTFOUND;
699     }
700
701     *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
702
703     if (TRACE_ON(ddraw)) {
704         TRACE("Returning surface %p with description : \n", *ppSurface);
705         DDRAW_dump_surface_desc(&(found->surface_desc));
706     }
707     
708     /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
709     IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
710     return DD_OK;
711 }
712
713 HRESULT WINAPI
714 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
715 {
716     TRACE("(%p)->(%08lx)\n",iface,dwFlags);
717
718     switch (dwFlags)
719     {
720     case DDGBS_CANBLT:
721     case DDGBS_ISBLTDONE:
722         return DD_OK;
723
724     default:
725         return DDERR_INVALIDPARAMS;
726     }
727 }
728
729 HRESULT WINAPI
730 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
731 {
732     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
733
734     TRACE("(%p)->(%p)\n",This,pCaps);
735     *pCaps = This->surface_desc.ddsCaps;
736     return DD_OK;
737 }
738
739 HRESULT WINAPI
740 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
741                                   LPDIRECTDRAWCLIPPER* ppClipper)
742 {
743     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
744
745     TRACE("(%p)->(%p)\n",This,ppClipper);
746     if (This->clipper == NULL)
747         return DDERR_NOCLIPPERATTACHED;
748
749     *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
750     IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
751                                              IDirectDrawClipper));
752     return DD_OK;
753 }
754
755 HRESULT WINAPI
756 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
757                                    LPDDCOLORKEY pCKey)
758 {
759     /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
760      * isn't there? That's like saying that an int isn't there. (Which MS
761      * has done in other docs.) */
762
763     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
764
765     TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
766     if (TRACE_ON(ddraw)) {
767         TRACE(" - colorkey flags : ");
768         DDRAW_dump_colorkeyflag(dwFlags);
769     }
770
771     switch (dwFlags)
772     {
773     case DDCKEY_DESTBLT:
774         *pCKey = This->surface_desc.ddckCKDestBlt;
775         break;
776
777     case DDCKEY_DESTOVERLAY:
778         *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
779         break;
780
781     case DDCKEY_SRCBLT:
782         *pCKey = This->surface_desc.ddckCKSrcBlt;
783         break;
784
785     case DDCKEY_SRCOVERLAY:
786         *pCKey = This->surface_desc.ddckCKSrcOverlay;
787         break;
788
789     default:
790         return DDERR_INVALIDPARAMS;
791     }
792
793     return DD_OK;
794 }
795
796 /* XXX We need to do something with the DC if the surface gets lost. */
797 HRESULT WINAPI
798 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
799 {
800     DDSURFACEDESC2 ddsd;
801     HRESULT hr;
802     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
803
804     TRACE("(%p)->(%p)\n",This,phDC);
805     CHECK_LOST(This);
806
807     LOCK_OBJECT(This);
808
809     if (This->dc_in_use)
810     {
811         UNLOCK_OBJECT(This);
812         return DDERR_DCALREADYCREATED;
813     }
814
815     /* Lock as per MSDN.
816      * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
817      * thread has it locked, but GetDC does not. */
818     ddsd.dwSize = sizeof(ddsd);
819     hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
820     if (FAILED(hr))
821     {
822         UNLOCK_OBJECT(This);
823         return hr;
824     }
825
826     hr = This->get_dc(This, &This->hDC);
827     if (SUCCEEDED(hr))
828     {
829         TRACE("returning %p\n",This->hDC);
830
831         *phDC = This->hDC;
832         This->dc_in_use = TRUE;
833     }
834     else WARN("No DC! Prepare for trouble\n");
835
836     UNLOCK_OBJECT(This);
837     return hr;
838 }
839
840 HRESULT WINAPI
841 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
842 {
843     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
844
845     TRACE("(%p)->(%p)\n",This,pDD);
846     *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
847     IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
848     return DD_OK;
849 }
850
851 HRESULT WINAPI
852 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
853 {
854     /* XXX: DDERR_INVALIDSURFACETYPE */
855
856     TRACE("(%p)->(%08lx)\n",iface,dwFlags);
857     switch (dwFlags)
858     {
859     case DDGFS_CANFLIP:
860     case DDGFS_ISFLIPDONE:
861         return DD_OK;
862
863     default:
864         return DDERR_INVALIDPARAMS;
865     }
866 }
867
868 HRESULT WINAPI
869 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
870 {
871     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
872
873     TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
874     CHECK_TEXTURE(This);
875
876     *pdwMaxLOD = This->max_lod;
877     return DD_OK;
878 }
879
880 HRESULT WINAPI
881 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
882                                           LPLONG pX, LPLONG pY)
883 {
884     return DDERR_NOTAOVERLAYSURFACE;
885 }
886
887 HRESULT WINAPI
888 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
889                                   LPDIRECTDRAWPALETTE* ppPalette)
890 {
891     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
892
893     TRACE("(%p)->(%p)\n",This,ppPalette);
894     if (This->palette == NULL)
895         return DDERR_NOPALETTEATTACHED;
896
897     *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
898     IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
899                                              IDirectDrawPalette));
900     return DD_OK;
901 }
902
903 HRESULT WINAPI
904 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
905                                       LPDDPIXELFORMAT pDDPixelFormat)
906 {
907     /* What is DDERR_INVALIDSURFACETYPE for here? */
908     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
909
910     TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
911     DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
912     return DD_OK;
913 }
914
915 HRESULT WINAPI
916 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
917                                    LPDWORD pdwPriority)
918 {
919     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
920
921     TRACE("(%p)->(%p)\n",This,pdwPriority);
922     CHECK_TEXTURE(This);
923
924     *pdwPriority = This->priority;
925     return DD_OK;
926 }
927
928 HRESULT WINAPI
929 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
930                                       REFGUID tag, LPVOID pBuffer,
931                                       LPDWORD pcbBufferSize)
932 {
933     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
934     PrivateData* data;
935
936     data = find_private_data(This, tag);
937     if (data == NULL) return DDERR_NOTFOUND;
938
939     /* This may not be right. */
940     if ((data->flags & DDSPD_VOLATILE)
941         && data->uniqueness_value != This->uniqueness_value)
942         return DDERR_EXPIRED;
943
944     if (*pcbBufferSize < data->size)
945     {
946         *pcbBufferSize = data->size;
947         return DDERR_MOREDATA;
948     }
949
950     if (data->flags & DDSPD_IUNKNOWNPTR)
951     {
952         *(LPUNKNOWN *)pBuffer = data->ptr.object;
953         IUnknown_AddRef(data->ptr.object);
954     }
955     else
956     {
957         memcpy(pBuffer, data->ptr.data, data->size);
958     }
959
960     return DD_OK;
961 }
962
963 HRESULT WINAPI
964 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
965                                       LPDDSURFACEDESC2 pDDSD)
966 {
967     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
968
969     TRACE("(%p)->(%p)\n",This,pDDSD);
970     if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
971         (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
972         ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
973         return DDERR_GENERIC;
974     }
975
976     DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
977     if (TRACE_ON(ddraw)) {
978       DDRAW_dump_surface_desc(pDDSD);
979     }
980     return DD_OK;
981 }
982
983 HRESULT WINAPI
984 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
985                                           LPDWORD pValue)
986 {
987     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
988
989     TRACE("(%p)->(%p)\n",This,pValue);
990     *pValue = This->uniqueness_value;
991     return DD_OK;
992 }
993
994 HRESULT WINAPI
995 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
996                                   LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
997 {
998     TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
999     return DDERR_ALREADYINITIALIZED;
1000 }
1001
1002 HRESULT WINAPI
1003 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
1004 {
1005     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1006
1007     TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
1008     return This->lost ? DDERR_SURFACELOST : DD_OK;
1009 }
1010
1011
1012 /* XXX This doesn't actually do any locking or keep track of the locked
1013  * rectangles. The behaviour is poorly documented. */
1014 HRESULT WINAPI
1015 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
1016                             LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
1017 {
1018     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1019
1020     if (TRACE_ON(ddraw)) {
1021         TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
1022         TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags);
1023     }
1024     if (WARN_ON(ddraw)) {
1025         if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY)) {
1026             WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY));
1027         }
1028     }
1029
1030     /* First, copy the Surface description */
1031     DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
1032
1033     /* Used to optimize the D3D Device locking */
1034     This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
1035     
1036     /* If asked only for a part, change the surface pointer.
1037      * (Not documented.) */
1038     if (prect != NULL) {
1039         TRACE(" lprect: %ldx%ld-%ldx%ld\n",
1040                 prect->left,prect->top,prect->right,prect->bottom);
1041         /* First do some sanity checkings on the rectangle we receive.
1042            DungeonSiege seems to gives us once a very bad rectangle for example */
1043         if ((prect->top < 0) ||
1044             (prect->left < 0) ||
1045             (prect->bottom < 0) ||
1046             (prect->right < 0) ||
1047             (prect->left >= prect->right) ||
1048             (prect->top >= prect->bottom) ||
1049             (prect->left >= This->surface_desc.dwWidth) ||
1050             (prect->right > This->surface_desc.dwWidth) ||
1051             (prect->top >= This->surface_desc.dwHeight) ||
1052             (prect->bottom > This->surface_desc.dwHeight)) {
1053             ERR(" Invalid values in LPRECT !!!\n");
1054             return DDERR_INVALIDPARAMS;
1055         }
1056
1057         This->lock_update(This, prect, flags);
1058
1059         pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1060             + prect->top * This->surface_desc.u1.lPitch
1061             + prect->left * GET_BPP(This->surface_desc);
1062     } else {
1063         This->lock_update(This, NULL, flags);
1064     }
1065
1066     TRACE("locked surface returning description : \n");
1067     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
1068     
1069     return DD_OK;
1070 }
1071
1072 HRESULT WINAPI
1073 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1074 {
1075     /* Some surface types should return DDERR_CANTPAGELOCK. */
1076     return DD_OK;
1077 }
1078
1079 HRESULT WINAPI
1080 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1081 {
1082     /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1083      * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1084     return DD_OK;
1085 }
1086
1087 HRESULT WINAPI
1088 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1089 {
1090     HRESULT hr;
1091     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1092
1093     TRACE("(%p)->(%p)\n",This,hDC);
1094
1095     if (!This->dc_in_use || This->hDC != hDC)
1096         return DDERR_INVALIDPARAMS;
1097
1098     This->release_dc(This, hDC);
1099
1100     hr = IDirectDrawSurface7_Unlock(iface, NULL);
1101     if (FAILED(hr)) return hr;
1102
1103     This->dc_in_use = FALSE;
1104     This->hDC = 0;
1105
1106     return DD_OK;
1107 }
1108
1109 /* Restore */
1110
1111 HRESULT WINAPI
1112 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
1113                                   LPDIRECTDRAWCLIPPER pDDClipper)
1114 {
1115     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1116
1117     TRACE("(%p)->(%p)\n",This,pDDClipper);
1118     if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
1119         return DD_OK;
1120
1121     if (This->clipper != NULL)
1122         IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1123                                                   IDirectDrawClipper));
1124
1125     This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1126                                 pDDClipper);
1127     if (pDDClipper != NULL)
1128         IDirectDrawClipper_AddRef(pDDClipper);
1129
1130     return DD_OK;
1131 }
1132
1133 HRESULT WINAPI
1134 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
1135                                    DWORD dwFlags, LPDDCOLORKEY pCKey)
1136 {
1137     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1138     
1139     TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
1140
1141     if (TRACE_ON(ddraw)) {
1142         TRACE(" - colorkey flags : ");
1143         DDRAW_dump_colorkeyflag(dwFlags);
1144     }
1145
1146     if ((dwFlags & DDCKEY_COLORSPACE) != 0) {
1147         FIXME(" colorkey value not supported (%08lx) !\n", dwFlags);
1148         return DDERR_INVALIDPARAMS;
1149     }
1150     
1151     /* TODO: investigate if this function can take multiple bits set at the same
1152              time (ie setting multiple colorkey values at the same time with only
1153              one API call).
1154     */
1155     if (pCKey) {
1156         switch (dwFlags & ~DDCKEY_COLORSPACE) {
1157             case DDCKEY_DESTBLT:
1158                 This->surface_desc.ddckCKDestBlt = *pCKey;
1159                 This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
1160                 break;
1161
1162             case DDCKEY_DESTOVERLAY:
1163                 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1164                 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1165                 break;
1166
1167             case DDCKEY_SRCOVERLAY:
1168                 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1169                 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1170                 break;
1171
1172             case DDCKEY_SRCBLT:
1173                 This->surface_desc.ddckCKSrcBlt = *pCKey;
1174                 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
1175                 break;
1176
1177             default:
1178                 return DDERR_INVALIDPARAMS;
1179         }
1180     } else {
1181         switch (dwFlags & ~DDCKEY_COLORSPACE) {
1182             case DDCKEY_DESTBLT:
1183                 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
1184                 break;
1185
1186             case DDCKEY_DESTOVERLAY:
1187                 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
1188                 break;
1189
1190             case DDCKEY_SRCOVERLAY:
1191                 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
1192                 break;
1193
1194             case DDCKEY_SRCBLT:
1195                 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
1196                 break;
1197
1198             default:
1199                 return DDERR_INVALIDPARAMS;
1200         }
1201     }
1202
1203     if (This->aux_setcolorkey_cb) This->aux_setcolorkey_cb(This, dwFlags, pCKey);
1204
1205     return DD_OK;
1206 }
1207
1208 HRESULT WINAPI
1209 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1210 {
1211     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1212
1213     TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1214     CHECK_TEXTURE(This);
1215
1216     This->max_lod = dwMaxLOD;
1217     return DD_OK;
1218 }
1219
1220 HRESULT WINAPI
1221 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1222                                           LONG X, LONG Y)
1223 {
1224     return DDERR_NOTAOVERLAYSURFACE;
1225 }
1226
1227 HRESULT WINAPI
1228 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1229                                   LPDIRECTDRAWPALETTE pPalette)
1230 {
1231     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1232     IDirectDrawPalette *pal_to_rel = NULL;
1233
1234     TRACE("(%p)->(%p)\n",This,pPalette);
1235     if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1236         return DD_OK;
1237
1238     if (This->palette != NULL) {
1239         if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1240             This->palette->global.dwFlags &= ~DDPCAPS_PRIMARYSURFACE;
1241         pal_to_rel = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
1242     }
1243
1244     This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1245                                 pPalette);
1246     if (pPalette != NULL) {
1247         IDirectDrawPalette_AddRef(pPalette);
1248         if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1249             This->palette->global.dwFlags |= DDPCAPS_PRIMARYSURFACE;
1250     }
1251
1252     This->set_palette(This, This->palette);
1253
1254     /* Do the palette release at the end to prevent doing some 'loop' when removing
1255      * the surface maintaining the last reference on a palette.
1256      */
1257     if (pal_to_rel != NULL)
1258         IDirectDrawPalette_Release(pal_to_rel);
1259
1260     return DD_OK;
1261 }
1262
1263 HRESULT WINAPI
1264 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1265                                    DWORD dwPriority)
1266 {
1267     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1268
1269     TRACE("(%p)->(%08lx)\n",This,dwPriority);
1270     CHECK_TEXTURE(This);
1271
1272     This->priority = dwPriority;
1273     return DD_OK;
1274 }
1275
1276 /* Be careful when locking this: it is risky to call the object's AddRef
1277  * or Release holding a lock. */
1278 HRESULT WINAPI
1279 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1280                                       REFGUID tag, LPVOID pData,
1281                                       DWORD cbSize, DWORD dwFlags)
1282 {
1283     PrivateData* data;
1284     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1285
1286     data = find_private_data(This, tag);
1287     if (data == NULL)
1288     {
1289         data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1290         if (data == NULL) return DDERR_OUTOFMEMORY;
1291
1292         data->tag = *tag;
1293         data->flags = dwFlags;
1294         data->uniqueness_value = This->uniqueness_value;
1295
1296         if (dwFlags & DDSPD_IUNKNOWNPTR)
1297         {
1298             data->ptr.object = (LPUNKNOWN)pData;
1299             data->size = sizeof(LPUNKNOWN);
1300             IUnknown_AddRef(data->ptr.object);
1301         }
1302         else
1303         {
1304             data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1305             if (data->ptr.data == NULL)
1306             {
1307                 HeapFree(GetProcessHeap(), 0, data);
1308                 return DDERR_OUTOFMEMORY;
1309             }
1310         }
1311
1312         /* link it in */
1313         data->next = This->private_data;
1314         data->prev = NULL;
1315         if (This->private_data)
1316             This->private_data->prev = data;
1317         This->private_data = data;
1318
1319         return DD_OK;
1320     }
1321     else
1322     {
1323         /* I don't actually know how windows handles this case. The only
1324          * reason I don't just call FreePrivateData is because I want to
1325          * guarantee SetPrivateData working when using LPUNKNOWN or data
1326          * that is no larger than the old data. */
1327
1328         return E_FAIL;
1329     }
1330 }
1331
1332 /* SetSurfaceDesc */
1333
1334 HRESULT WINAPI
1335 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1336 {
1337     ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1338
1339     TRACE("(%p)->Unlock(%p)\n",This,pRect);
1340
1341     This->unlock_update(This, pRect);
1342     if (This->aux_unlock)
1343         This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1344
1345     return DD_OK;
1346 }
1347
1348 HRESULT WINAPI
1349 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1350                                      LPRECT pSrcRect,
1351                                      LPDIRECTDRAWSURFACE7 pDstSurface,
1352                                      LPRECT pDstRect, DWORD dwFlags,
1353                                      LPDDOVERLAYFX pFX)
1354 {
1355     return DDERR_UNSUPPORTED;
1356 }
1357
1358 /* MSDN: "not currently implemented." */
1359 HRESULT WINAPI
1360 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1361                                             DWORD dwFlags)
1362 {
1363     return DDERR_UNSUPPORTED;
1364 }
1365
1366 HRESULT WINAPI
1367 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1368                                            DWORD dwFlags,
1369                                            LPDIRECTDRAWSURFACE7 pDDSRef)
1370 {
1371     return DDERR_NOTAOVERLAYSURFACE;
1372 }