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