fdopen: don't rewind the file after creating the FILE* handle. Added
[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 #include "winerror.h"
23
24 #include <assert.h>
25 #include <string.h>
26
27 #include "mesa_private.h"
28 #include "wine/debug.h"
29 #include "ddraw_private.h"
30 #include "dsurface/main.h"
31 #include "ddraw/main.h"
32 #include "dsurface/thunks.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
35
36 /** Creation/Destruction functions */
37
38 HRESULT
39 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
40                                  IDirectDrawImpl *pDD,
41                                  const DDSURFACEDESC2 *pDDSD)
42 {
43     TRACE("(%p)->(%p,%p)\n", This, pDD, pDDSD);
44
45     if (pDDSD != &This->surface_desc) {
46         This->surface_desc.dwSize = sizeof(This->surface_desc);
47         DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
48     }
49     This->uniqueness_value = 1; /* unchecked */
50     This->ref = 1;
51
52     This->local.lpSurfMore = &This->more;
53     This->local.lpGbl = &This->global;
54     This->local.dwProcessId = GetCurrentProcessId();
55     This->local.dwFlags = 0; /* FIXME */
56     This->local.ddsCaps.dwCaps = This->surface_desc.ddsCaps.dwCaps;
57     /* FIXME: more local stuff */
58     This->more.lpDD_lcl = &pDD->local;
59     This->more.ddsCapsEx.dwCaps2 = This->surface_desc.ddsCaps.dwCaps2;
60     This->more.ddsCapsEx.dwCaps3 = This->surface_desc.ddsCaps.dwCaps3;
61     This->more.ddsCapsEx.dwCaps4 = This->surface_desc.ddsCaps.dwCaps4;
62     /* FIXME: more more stuff */
63     This->gmore = &This->global_more;
64     This->global.u3.lpDD = pDD->local.lpGbl;
65     /* FIXME: more global stuff */
66
67     This->final_release = Main_DirectDrawSurface_final_release;
68     This->late_allocate = Main_DirectDrawSurface_late_allocate;
69     This->attach = Main_DirectDrawSurface_attach;
70     This->detach = Main_DirectDrawSurface_detach;
71     This->lock_update = Main_DirectDrawSurface_lock_update;
72     This->unlock_update = Main_DirectDrawSurface_unlock_update;
73     This->lose_surface = Main_DirectDrawSurface_lose_surface;
74     This->set_palette    = Main_DirectDrawSurface_set_palette;
75     This->update_palette = Main_DirectDrawSurface_update_palette;
76     This->get_display_window = Main_DirectDrawSurface_get_display_window;
77     This->get_gamma_ramp = Main_DirectDrawSurface_get_gamma_ramp;
78     This->set_gamma_ramp = Main_DirectDrawSurface_set_gamma_ramp;
79
80     ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
81                         DDRAW_IDDS3_Thunk_VTable);
82     ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
83                         DDRAW_IDDGC_VTable);
84
85     /* There is no generic implementation of IDDS7 or texture */
86
87     Main_DirectDraw_AddSurface(pDD, This);
88     return DD_OK;
89 }
90
91 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
92 {
93     Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
94 }
95
96 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
97 {
98     return DD_OK;
99 }
100
101 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
102 {
103     This->final_release(This);
104     if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
105     if (This->tex_private) HeapFree(GetProcessHeap(), 0, This->tex_private);
106     HeapFree(GetProcessHeap(), 0, This);
107 }
108
109 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
110 {
111     WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
112     Main_DirectDrawSurface_Destroy(This);
113 }
114
115 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
116 {
117     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
118
119     TRACE("(%p)->(): decreasing from %ld\n", This, This->ref);
120     
121     if (--This->ref == 0)
122     {
123         if (This->aux_release)
124             This->aux_release(This->aux_ctx, This->aux_data);
125         Main_DirectDrawSurface_Destroy(This);
126
127         TRACE("released surface %p\n", This);
128         
129         return 0;
130     }
131
132     return This->ref;
133 }
134
135 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
136 {
137     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
138
139     TRACE("(%p)->(): increasing from %ld\n", This, This->ref);
140     
141     return ++This->ref;
142 }
143
144 HRESULT WINAPI
145 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
146                                       LPVOID* ppObj)
147 {
148     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
149     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
150
151     *ppObj = NULL;
152
153     if (IsEqualGUID(&IID_IUnknown, riid)
154         || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
155         || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
156     {
157         This->ref++;
158         *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
159         return S_OK;
160     }
161     else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
162              || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
163              || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
164     {
165         This->ref++;
166         *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
167         return S_OK;
168     }
169     else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
170     {
171         This->ref++;
172         *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
173         return S_OK;
174     }
175 #ifdef HAVE_OPENGL
176     else if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL, riid ) ||
177               IsEqualGUID( &IID_IDirect3DHALDevice, riid) )
178     {
179         IDirect3DDeviceImpl *d3ddevimpl;
180         HRESULT ret_value;
181
182         ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner->d3d, This);
183         if (FAILED(ret_value)) return ret_value;
184
185         *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
186         TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj);
187         
188         This->ref++; /* No idea if this is correct.. Need to check using real Windows */
189         return ret_value;
190     }
191     else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
192              IsEqualGUID( &IID_IDirect3DTexture2, riid ))
193     {
194         HRESULT ret_value = S_OK;
195
196         /* In case the texture surface was created before the D3D creation */
197         if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) == 0) return E_NOINTERFACE;
198         /* Create a 'delayed' private field only if it is not an offscreen texture... */
199         if (This->tex_private == NULL) {
200             if (This->ddraw_owner->d3d == NULL) {
201                 ERR("Texture created with no D3D object yet.. Not supported !\n");
202                 return E_NOINTERFACE;
203             }
204
205             if (((This->surface_desc.dwFlags & DDSD_MIPMAPCOUNT) &&
206                  (This->surface_desc.u2.dwMipMapCount > 1)) ||
207                 (This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)) {
208                 ERR(" need to fix mipmaping in this case !!\n");
209             }
210
211             ret_value = This->ddraw_owner->d3d->create_texture(This->ddraw_owner->d3d, This, FALSE, NULL, 0);
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         DPRINTF("   Caps are : "); DDRAW_dump_DDSCAPS2(pCaps); DPRINTF("\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             DPRINTF("   Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps); DPRINTF("\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             DPRINTF("   Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf->surface_desc.ddsCaps)); DPRINTF("\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     switch (dwFlags)
741     {
742     case DDCKEY_DESTBLT:
743         *pCKey = This->surface_desc.ddckCKDestBlt;
744         break;
745
746     case DDCKEY_DESTOVERLAY:
747         *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
748         break;
749
750     case DDCKEY_SRCBLT:
751         *pCKey = This->surface_desc.ddckCKSrcBlt;
752         break;
753
754     case DDCKEY_SRCOVERLAY:
755         *pCKey = This->surface_desc.ddckCKSrcOverlay;
756         break;
757
758     default:
759         return DDERR_INVALIDPARAMS;
760     }
761
762     return DD_OK;
763 }
764
765 /* XXX We need to do something with the DC if the surface gets lost. */
766 HRESULT WINAPI
767 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
768 {
769     DDSURFACEDESC2 ddsd;
770     HRESULT hr;
771     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
772
773     TRACE("(%p)->(%p)\n",This,phDC);
774     CHECK_LOST(This);
775
776     LOCK_OBJECT(This);
777
778     if (This->dc_in_use)
779     {
780         UNLOCK_OBJECT(This);
781         return DDERR_DCALREADYCREATED;
782     }
783
784     /* Lock as per MSDN.
785      * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
786      * thread has it locked, but GetDC does not. */
787     ddsd.dwSize = sizeof(ddsd);
788     hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, DDLOCK_READONLY, 0);
789     if (FAILED(hr))
790     {
791         UNLOCK_OBJECT(This);
792         return hr;
793     }
794
795     hr = This->get_dc(This, &This->hDC);
796     if (SUCCEEDED(hr))
797     {
798         TRACE("returning %p\n",This->hDC);
799
800         *phDC = This->hDC;
801         This->dc_in_use = TRUE;
802     }
803     else WARN("No DC! Prepare for trouble\n");
804
805     UNLOCK_OBJECT(This);
806     return hr;
807 }
808
809 HRESULT WINAPI
810 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
811 {
812     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
813
814     TRACE("(%p)->(%p)\n",This,pDD);
815     *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
816     IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
817     return DD_OK;
818 }
819
820 HRESULT WINAPI
821 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
822 {
823     /* XXX: DDERR_INVALIDSURFACETYPE */
824
825     TRACE("(%p)->(%08lx)\n",iface,dwFlags);
826     switch (dwFlags)
827     {
828     case DDGFS_CANFLIP:
829     case DDGFS_ISFLIPDONE:
830         return DD_OK;
831
832     default:
833         return DDERR_INVALIDPARAMS;
834     }
835 }
836
837 HRESULT WINAPI
838 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
839 {
840     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
841
842     TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
843     CHECK_TEXTURE(This);
844
845     *pdwMaxLOD = This->max_lod;
846     return DD_OK;
847 }
848
849 HRESULT WINAPI
850 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
851                                           LPLONG pX, LPLONG pY)
852 {
853     return DDERR_NOTAOVERLAYSURFACE;
854 }
855
856 HRESULT WINAPI
857 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
858                                   LPDIRECTDRAWPALETTE* ppPalette)
859 {
860     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
861
862     TRACE("(%p)->(%p)\n",This,ppPalette);
863     if (This->palette == NULL)
864         return DDERR_NOPALETTEATTACHED;
865
866     *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
867     IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
868                                              IDirectDrawPalette));
869     return DD_OK;
870 }
871
872 HRESULT WINAPI
873 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
874                                       LPDDPIXELFORMAT pDDPixelFormat)
875 {
876     /* What is DDERR_INVALIDSURFACETYPE for here? */
877     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
878
879     TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
880     DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
881     return DD_OK;
882 }
883
884 HRESULT WINAPI
885 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
886                                    LPDWORD pdwPriority)
887 {
888     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
889
890     TRACE("(%p)->(%p)\n",This,pdwPriority);
891     CHECK_TEXTURE(This);
892
893     *pdwPriority = This->priority;
894     return DD_OK;
895 }
896
897 HRESULT WINAPI
898 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
899                                       REFGUID tag, LPVOID pBuffer,
900                                       LPDWORD pcbBufferSize)
901 {
902     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
903     PrivateData* data;
904
905     data = find_private_data(This, tag);
906     if (data == NULL) return DDERR_NOTFOUND;
907
908     /* This may not be right. */
909     if ((data->flags & DDSPD_VOLATILE)
910         && data->uniqueness_value != This->uniqueness_value)
911         return DDERR_EXPIRED;
912
913     if (*pcbBufferSize < data->size)
914     {
915         *pcbBufferSize = data->size;
916         return DDERR_MOREDATA;
917     }
918
919     if (data->flags & DDSPD_IUNKNOWNPTR)
920     {
921         *(LPUNKNOWN *)pBuffer = data->ptr.object;
922         IUnknown_AddRef(data->ptr.object);
923     }
924     else
925     {
926         memcpy(pBuffer, data->ptr.data, data->size);
927     }
928
929     return DD_OK;
930 }
931
932 HRESULT WINAPI
933 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
934                                       LPDDSURFACEDESC2 pDDSD)
935 {
936     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
937
938     TRACE("(%p)->(%p)\n",This,pDDSD);
939     if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
940         (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
941         ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
942         return DDERR_GENERIC;
943     }
944
945     DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
946     if (TRACE_ON(ddraw)) {
947       DDRAW_dump_surface_desc(pDDSD);
948     }
949     return DD_OK;
950 }
951
952 HRESULT WINAPI
953 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
954                                           LPDWORD pValue)
955 {
956     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
957
958     TRACE("(%p)->(%p)\n",This,pValue);
959     *pValue = This->uniqueness_value;
960     return DD_OK;
961 }
962
963 HRESULT WINAPI
964 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
965                                   LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
966 {
967     TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
968     return DDERR_ALREADYINITIALIZED;
969 }
970
971 HRESULT WINAPI
972 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
973 {
974     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
975
976     TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
977     return This->lost ? DDERR_SURFACELOST : DD_OK;
978 }
979
980
981 /* XXX This doesn't actually do any locking or keep track of the locked
982  * rectangles. The behaviour is poorly documented. */
983 HRESULT WINAPI
984 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
985                             LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
986 {
987     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
988
989     if (TRACE_ON(ddraw)) {
990         TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
991         TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags);
992     }
993
994     if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
995         WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
996                  This,prect,pDDSD,flags,(DWORD)h);
997
998     /* First, copy the Surface description */
999     DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
1000
1001     TRACE("locked surface returning description : \n");
1002     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
1003
1004     /* Used to optimize the D3D Device locking */
1005     This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
1006     
1007     /* If asked only for a part, change the surface pointer.
1008      * (Not documented.) */
1009     if (prect != NULL) {
1010         TRACE(" lprect: %dx%d-%dx%d\n",
1011                 prect->top,prect->left,prect->bottom,prect->right
1012         );
1013         if ((prect->top < 0) ||
1014             (prect->left < 0) ||
1015             (prect->bottom < 0) ||
1016             (prect->right < 0)) {
1017           ERR(" Negative values in LPRECT !!!\n");
1018           return DDERR_INVALIDPARAMS;
1019        }
1020
1021         This->lock_update(This, prect, flags);
1022
1023         pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1024             + prect->top * This->surface_desc.u1.lPitch
1025             + prect->left * GET_BPP(This->surface_desc);
1026     } else {
1027         This->lock_update(This, NULL, flags);
1028     }
1029
1030     return DD_OK;
1031 }
1032
1033 HRESULT WINAPI
1034 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1035 {
1036     /* Some surface types should return DDERR_CANTPAGELOCK. */
1037     return DD_OK;
1038 }
1039
1040 HRESULT WINAPI
1041 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1042 {
1043     /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1044      * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1045     return DD_OK;
1046 }
1047
1048 HRESULT WINAPI
1049 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1050 {
1051     HRESULT hr;
1052     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1053
1054     TRACE("(%p)->(%p)\n",This,hDC);
1055
1056     if (!This->dc_in_use || This->hDC != hDC)
1057         return DDERR_INVALIDPARAMS;
1058
1059     This->release_dc(This, hDC);
1060
1061     hr = IDirectDrawSurface7_Unlock(iface, NULL);
1062     if (FAILED(hr)) return hr;
1063
1064     This->dc_in_use = FALSE;
1065     This->hDC = 0;
1066
1067     return DD_OK;
1068 }
1069
1070 /* Restore */
1071
1072 HRESULT WINAPI
1073 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
1074                                   LPDIRECTDRAWCLIPPER pDDClipper)
1075 {
1076     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1077
1078     TRACE("(%p)->(%p)\n",This,pDDClipper);
1079     if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
1080         return DD_OK;
1081
1082     if (This->clipper != NULL)
1083         IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1084                                                   IDirectDrawClipper));
1085
1086     This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1087                                 pDDClipper);
1088     if (pDDClipper != NULL)
1089         IDirectDrawClipper_AddRef(pDDClipper);
1090
1091     return DD_OK;
1092 }
1093
1094 HRESULT WINAPI
1095 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
1096                                    DWORD dwFlags, LPDDCOLORKEY pCKey)
1097 {
1098     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1099
1100     TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
1101     if (pCKey == NULL)
1102     {
1103         FIXME("supposedly removing color key %lu\n",
1104               dwFlags & ~DDCKEY_COLORSPACE);
1105         return DD_OK;
1106     }
1107
1108     switch (dwFlags & ~DDCKEY_COLORSPACE)
1109     {
1110     case DDCKEY_DESTBLT:
1111         This->surface_desc.ddckCKDestBlt = *pCKey;
1112         break;
1113
1114     case DDCKEY_DESTOVERLAY:
1115         This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1116         break;
1117
1118     case DDCKEY_SRCOVERLAY:
1119         This->surface_desc.ddckCKSrcOverlay = *pCKey;
1120         break;
1121
1122     case DDCKEY_SRCBLT:
1123         This->surface_desc.ddckCKSrcBlt = *pCKey;
1124         break;
1125
1126     default:
1127         return DDERR_INVALIDPARAMS;
1128     }
1129
1130     return DD_OK;
1131 }
1132
1133 HRESULT WINAPI
1134 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1135 {
1136     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1137
1138     TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1139     CHECK_TEXTURE(This);
1140
1141     This->max_lod = dwMaxLOD;
1142     return DD_OK;
1143 }
1144
1145 HRESULT WINAPI
1146 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1147                                           LONG X, LONG Y)
1148 {
1149     return DDERR_NOTAOVERLAYSURFACE;
1150 }
1151
1152 HRESULT WINAPI
1153 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1154                                   LPDIRECTDRAWPALETTE pPalette)
1155 {
1156     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1157
1158     TRACE("(%p)->(%p)\n",This,pPalette);
1159     if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1160         return DD_OK;
1161
1162     if (This->palette != NULL) {
1163         if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1164             This->palette->global.dwFlags &= ~DDPCAPS_PRIMARYSURFACE;
1165         IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette,
1166                                                   IDirectDrawPalette));
1167     }
1168
1169     This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1170                                 pPalette);
1171     if (pPalette != NULL) {
1172         IDirectDrawPalette_AddRef(pPalette);
1173         if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1174             This->palette->global.dwFlags |= DDPCAPS_PRIMARYSURFACE;
1175     }
1176
1177     This->set_palette(This, This->palette);
1178
1179     return DD_OK;
1180 }
1181
1182 HRESULT WINAPI
1183 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1184                                    DWORD dwPriority)
1185 {
1186     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1187
1188     TRACE("(%p)->(%08lx)\n",This,dwPriority);
1189     CHECK_TEXTURE(This);
1190
1191     This->priority = dwPriority;
1192     return DD_OK;
1193 }
1194
1195 /* Be careful when locking this: it is risky to call the object's AddRef
1196  * or Release holding a lock. */
1197 HRESULT WINAPI
1198 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1199                                       REFGUID tag, LPVOID pData,
1200                                       DWORD cbSize, DWORD dwFlags)
1201 {
1202     PrivateData* data;
1203     ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1204
1205     data = find_private_data(This, tag);
1206     if (data == NULL)
1207     {
1208         data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1209         if (data == NULL) return DDERR_OUTOFMEMORY;
1210
1211         data->tag = *tag;
1212         data->flags = dwFlags;
1213         data->uniqueness_value = This->uniqueness_value;
1214
1215         if (dwFlags & DDSPD_IUNKNOWNPTR)
1216         {
1217             data->ptr.object = (LPUNKNOWN)pData;
1218             data->size = sizeof(LPUNKNOWN);
1219             IUnknown_AddRef(data->ptr.object);
1220         }
1221         else
1222         {
1223             data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1224             if (data->ptr.data == NULL)
1225             {
1226                 HeapFree(GetProcessHeap(), 0, data);
1227                 return DDERR_OUTOFMEMORY;
1228             }
1229         }
1230
1231         /* link it in */
1232         data->next = This->private_data;
1233         data->prev = NULL;
1234         if (This->private_data)
1235             This->private_data->prev = data;
1236         This->private_data = data;
1237
1238         return DD_OK;
1239     }
1240     else
1241     {
1242         /* I don't actually know how windows handles this case. The only
1243          * reason I don't just call FreePrivateData is because I want to
1244          * guarantee SetPrivateData working when using LPUNKNOWN or data
1245          * that is no larger than the old data. */
1246
1247         return E_FAIL;
1248     }
1249 }
1250
1251 /* SetSurfaceDesc */
1252
1253 HRESULT WINAPI
1254 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1255 {
1256     ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1257
1258     TRACE("(%p)->Unlock(%p)\n",This,pRect);
1259
1260     This->unlock_update(This, pRect);
1261     if (This->aux_unlock)
1262         This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1263
1264     return DD_OK;
1265 }
1266
1267 HRESULT WINAPI
1268 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1269                                      LPRECT pSrcRect,
1270                                      LPDIRECTDRAWSURFACE7 pDstSurface,
1271                                      LPRECT pDstRect, DWORD dwFlags,
1272                                      LPDDOVERLAYFX pFX)
1273 {
1274     return DDERR_UNSUPPORTED;
1275 }
1276
1277 /* MSDN: "not currently implemented." */
1278 HRESULT WINAPI
1279 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1280                                             DWORD dwFlags)
1281 {
1282     return DDERR_UNSUPPORTED;
1283 }
1284
1285 HRESULT WINAPI
1286 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1287                                            DWORD dwFlags,
1288                                            LPDIRECTDRAWSURFACE7 pDDSRef)
1289 {
1290     return DDERR_NOTAOVERLAYSURFACE;
1291 }