Add the possibility to save a snapshot of the backbuffer at
[wine/dcerpc.git] / dlls / ddraw / dsurface / main.c
blob7198138ff06c062d9803a44a44588fbc6965e3b6
1 /* DirectDrawSurface base implementation
3 * Copyright 1997-2000 Marcus Meissner
4 * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5 * Copyright 2000-2001 TransGaming Technologies Inc.
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.
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.
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
21 #include "config.h"
23 #include <assert.h>
24 #include <string.h>
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"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 WINE_DECLARE_DEBUG_CHANNEL(ddraw_flip);
39 /** Creation/Destruction functions */
41 HRESULT
42 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
43 IDirectDrawImpl *pDD,
44 const DDSURFACEDESC2 *pDDSD)
46 TRACE("(%p)->(%p,%p)\n", This, pDD, pDDSD);
48 if (pDDSD != &This->surface_desc) {
49 This->surface_desc.dwSize = sizeof(This->surface_desc);
50 DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
52 This->uniqueness_value = 1; /* unchecked */
53 This->ref = 1;
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 */
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;
83 ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
84 DDRAW_IDDS3_Thunk_VTable);
85 ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
86 DDRAW_IDDGC_VTable);
88 /* There is no generic implementation of IDDS7 or texture */
90 Main_DirectDraw_AddSurface(pDD, This);
91 return DD_OK;
94 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
96 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
99 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
101 return DD_OK;
104 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
106 if (This->palette) {
107 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette, IDirectDrawPalette));
108 This->palette = NULL;
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);
116 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
118 WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
119 Main_DirectDrawSurface_Destroy(This);
122 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
124 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
126 TRACE("(%p)->(): decreasing from %ld\n", This, This->ref);
128 if (--This->ref == 0)
130 if (This->aux_release)
131 This->aux_release(This->aux_ctx, This->aux_data);
132 Main_DirectDrawSurface_Destroy(This);
134 TRACE("released surface %p\n", This);
136 return 0;
139 return This->ref;
142 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
144 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
146 TRACE("(%p)->(): increasing from %ld\n", This, This->ref);
148 return ++This->ref;
151 HRESULT WINAPI
152 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
153 LPVOID* ppObj)
155 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
156 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
158 *ppObj = NULL;
160 if (IsEqualGUID(&IID_IUnknown, riid)
161 || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
162 || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
164 This->ref++;
165 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
166 return S_OK;
168 else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
169 || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
170 || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
172 This->ref++;
173 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
174 return S_OK;
176 else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
178 This->ref++;
179 *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
180 return S_OK;
182 #ifdef HAVE_OPENGL
183 /* interfaces following here require OpenGL */
184 if( !opengl_initialized )
185 return E_NOINTERFACE;
187 if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL, riid ) ||
188 IsEqualGUID( &IID_IDirect3DHALDevice, riid) )
190 IDirect3DDeviceImpl *d3ddevimpl;
191 HRESULT ret_value;
193 ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, TRUE);
194 if (FAILED(ret_value)) return ret_value;
196 *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
197 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj);
199 This->ref++; /* No idea if this is correct.. Need to check using real Windows */
200 return ret_value;
202 else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
203 IsEqualGUID( &IID_IDirect3DTexture2, riid ))
205 HRESULT ret_value = S_OK;
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.
211 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
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;
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;
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);
230 This->ref++;
231 return ret_value;
233 #endif
235 return E_NOINTERFACE;
238 /*** Callbacks */
240 BOOL
241 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
242 IDirectDrawSurfaceImpl *to)
244 return TRUE;
247 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
249 return TRUE;
252 void
253 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
254 DWORD dwFlags)
258 void
259 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
260 LPCRECT pRect)
264 void
265 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
269 void
270 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
271 IDirectDrawPaletteImpl* pal)
275 void
276 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
277 IDirectDrawPaletteImpl* pal,
278 DWORD dwStart, DWORD dwCount,
279 LPPALETTEENTRY palent)
283 HWND
284 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
286 return 0;
289 HRESULT
290 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
291 DWORD dwFlags,
292 LPDDGAMMARAMP lpGammaRamp)
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;
303 HRESULT
304 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
305 DWORD dwFlags,
306 LPDDGAMMARAMP lpGammaRamp)
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;
318 /*** Interface functions */
320 HRESULT WINAPI
321 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
322 LPDIRECTDRAWSURFACE7 pAttach)
324 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
325 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
326 IDirectDrawSurface7, pAttach);
328 TRACE("(%p)->(%p)\n",This,pAttach);
330 /* Does windows check this? */
331 if (surf == This)
332 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
334 /* Does windows check this? */
335 if (surf->ddraw_owner != This->ddraw_owner)
336 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
338 if (surf->surface_owner != NULL)
339 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
341 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
342 * But apparently backbuffers and mipmaps can be attached too. */
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) */
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;
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;
365 IDirectDrawSurface7_AddRef(pAttach);
367 return DD_OK;
370 /* MSDN: "not currently implemented." */
371 HRESULT WINAPI
372 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
373 LPRECT pRect)
375 TRACE("(%p)->(%p)\n",iface,pRect);
376 return DDERR_UNSUPPORTED; /* unchecked */
379 /* MSDN: "not currently implemented." */
380 HRESULT WINAPI
381 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
382 LPDDBLTBATCH pBatch, DWORD dwCount,
383 DWORD dwFlags)
385 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
386 return DDERR_UNSUPPORTED; /* unchecked */
389 HRESULT WINAPI
390 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
392 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
393 volatile IDirectDrawSurfaceImpl* vThis = This;
395 TRACE("(%p)\n",This);
396 /* A uniquness value of 0 is apparently special.
397 * This needs to be checked. */
398 while (1)
400 DWORD old_uniqueness_value = vThis->uniqueness_value;
401 DWORD new_uniqueness_value = old_uniqueness_value+1;
403 if (old_uniqueness_value == 0) break;
404 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
406 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
407 old_uniqueness_value,
408 new_uniqueness_value)
409 == old_uniqueness_value)
410 break;
413 return DD_OK;
416 HRESULT WINAPI
417 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
418 DWORD dwFlags,
419 LPDIRECTDRAWSURFACE7 pAttach)
421 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
422 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
423 IDirectDrawSurface7, pAttach);
425 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
427 if (!surf || (surf->surface_owner != This))
428 return DDERR_SURFACENOTATTACHED; /* unchecked */
430 surf->detach(surf);
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 */
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;
447 IDirectDrawSurface7_Release(pAttach);
449 return DD_OK;
452 HRESULT WINAPI
453 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
454 LPVOID context,
455 LPDDENUMSURFACESCALLBACK7 cb)
457 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
458 IDirectDrawSurfaceImpl* surf;
460 TRACE("(%p)->(%p,%p)\n",This,context,cb);
462 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
464 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
465 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
466 context) == DDENUMRET_CANCEL)
467 break;
470 return DD_OK;
473 HRESULT WINAPI
474 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
475 DWORD dwFlags, LPVOID context,
476 LPDDENUMSURFACESCALLBACK7 cb)
478 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
479 return DD_OK;
482 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
483 IDirectDrawSurfaceImpl* back,
484 DWORD dwFlags)
486 /* uniqueness_value? */
487 /* This is necessary. But is it safe? */
489 HDC tmp = front->hDC;
490 front->hDC = back->hDC;
491 back->hDC = tmp;
495 BOOL tmp = front->dc_in_use;
496 front->dc_in_use = back->dc_in_use;
497 back->dc_in_use = tmp;
501 FLATPTR tmp = front->global.fpVidMem;
502 front->global.fpVidMem = back->global.fpVidMem;
503 back->global.fpVidMem = tmp;
507 ULONG_PTR tmp = front->global_more.hKernelSurface;
508 front->global_more.hKernelSurface = back->global_more.hKernelSurface;
509 back->global_more.hKernelSurface = tmp;
512 return TRUE;
515 HRESULT WINAPI
516 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
517 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
519 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
520 IDirectDrawSurfaceImpl* target;
521 HRESULT hr;
523 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
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;
531 if (This->aux_flip)
532 if (This->aux_flip(This->aux_ctx, This->aux_data))
533 return DD_OK;
535 /* 1. find the flip target */
536 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
537 if (override == NULL)
539 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
540 LPDIRECTDRAWSURFACE7 tgt;
542 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
543 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
545 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
546 tgt);
547 IDirectDrawSurface7_Release(tgt);
549 else
551 BOOL on_chain = FALSE;
552 IDirectDrawSurfaceImpl* surf;
554 /* MSDN: "The method fails if the specified [override] surface is not
555 * a member of the flipping chain." */
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);
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)
567 if (surf == This)
569 on_chain = TRUE;
570 break;
574 if (!on_chain)
575 return DDERR_INVALIDPARAMS; /* unchecked */
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;
585 /* Hack for paletted games... */
586 palette = target->palette;
587 target->palette = This->palette;
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;
596 if (This->flip_data(This, target, dwFlags))
597 This->flip_update(This, dwFlags);
599 return DD_OK;
602 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
603 REFGUID tag)
605 PrivateData* data;
606 for (data = This->private_data; data != NULL; data = data->next)
608 if (IsEqualGUID(&data->tag, tag)) break;
611 return data;
614 HRESULT WINAPI
615 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
617 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
618 PrivateData *data;
620 data = find_private_data(This, tag);
621 if (data == NULL) return DDERR_NOTFOUND;
623 if (data->prev)
624 data->prev->next = data->next;
625 if (data->next)
626 data->next->prev = data->prev;
628 if (data->flags & DDSPD_IUNKNOWNPTR)
630 if (data->ptr.object != NULL)
631 IUnknown_Release(data->ptr.object);
633 else
634 HeapFree(GetProcessHeap(), 0, data->ptr.data);
636 HeapFree(GetProcessHeap(), 0, data);
638 return DD_OK;
641 HRESULT WINAPI
642 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
643 LPDDSCAPS2 pCaps,
644 LPDIRECTDRAWSURFACE7* ppSurface)
646 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
647 IDirectDrawSurfaceImpl* surf;
648 IDirectDrawSurfaceImpl* found = NULL;
649 DDSCAPS2 our_caps;
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");
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");
669 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
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");
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))
682 /* MSDN: "This method fails if more than one surface is attached
683 * that matches the capabilities requested." */
684 if (found != NULL)
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. */
692 found = surf;
696 if (found == NULL) {
697 TRACE("Did not find any valid surface\n");
698 return DDERR_NOTFOUND;
701 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
703 if (TRACE_ON(ddraw)) {
704 TRACE("Returning surface %p with description : \n", *ppSurface);
705 DDRAW_dump_surface_desc(&(found->surface_desc));
708 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
709 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
710 return DD_OK;
713 HRESULT WINAPI
714 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
716 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
718 switch (dwFlags)
720 case DDGBS_CANBLT:
721 case DDGBS_ISBLTDONE:
722 return DD_OK;
724 default:
725 return DDERR_INVALIDPARAMS;
729 HRESULT WINAPI
730 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
732 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
734 TRACE("(%p)->(%p)\n",This,pCaps);
735 *pCaps = This->surface_desc.ddsCaps;
736 return DD_OK;
739 HRESULT WINAPI
740 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
741 LPDIRECTDRAWCLIPPER* ppClipper)
743 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
745 TRACE("(%p)->(%p)\n",This,ppClipper);
746 if (This->clipper == NULL)
747 return DDERR_NOCLIPPERATTACHED;
749 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
750 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
751 IDirectDrawClipper));
752 return DD_OK;
755 HRESULT WINAPI
756 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
757 LPDDCOLORKEY pCKey)
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.) */
763 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
765 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
766 if (TRACE_ON(ddraw)) {
767 TRACE(" - colorkey flags : ");
768 DDRAW_dump_colorkeyflag(dwFlags);
771 switch (dwFlags)
773 case DDCKEY_DESTBLT:
774 *pCKey = This->surface_desc.ddckCKDestBlt;
775 break;
777 case DDCKEY_DESTOVERLAY:
778 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
779 break;
781 case DDCKEY_SRCBLT:
782 *pCKey = This->surface_desc.ddckCKSrcBlt;
783 break;
785 case DDCKEY_SRCOVERLAY:
786 *pCKey = This->surface_desc.ddckCKSrcOverlay;
787 break;
789 default:
790 return DDERR_INVALIDPARAMS;
793 return DD_OK;
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)
800 DDSURFACEDESC2 ddsd;
801 HRESULT hr;
802 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
804 TRACE("(%p)->(%p)\n",This,phDC);
805 CHECK_LOST(This);
807 LOCK_OBJECT(This);
809 if (This->dc_in_use)
811 UNLOCK_OBJECT(This);
812 return DDERR_DCALREADYCREATED;
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))
822 UNLOCK_OBJECT(This);
823 return hr;
826 hr = This->get_dc(This, &This->hDC);
827 if (SUCCEEDED(hr))
829 TRACE("returning %p\n",This->hDC);
831 *phDC = This->hDC;
832 This->dc_in_use = TRUE;
834 else WARN("No DC! Prepare for trouble\n");
836 UNLOCK_OBJECT(This);
837 return hr;
840 HRESULT WINAPI
841 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
843 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
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;
851 HRESULT WINAPI
852 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
854 /* XXX: DDERR_INVALIDSURFACETYPE */
856 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
857 switch (dwFlags)
859 case DDGFS_CANFLIP:
860 case DDGFS_ISFLIPDONE:
861 return DD_OK;
863 default:
864 return DDERR_INVALIDPARAMS;
868 HRESULT WINAPI
869 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
871 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
873 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
874 CHECK_TEXTURE(This);
876 *pdwMaxLOD = This->max_lod;
877 return DD_OK;
880 HRESULT WINAPI
881 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
882 LPLONG pX, LPLONG pY)
884 return DDERR_NOTAOVERLAYSURFACE;
887 HRESULT WINAPI
888 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
889 LPDIRECTDRAWPALETTE* ppPalette)
891 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
893 TRACE("(%p)->(%p)\n",This,ppPalette);
894 if (This->palette == NULL)
895 return DDERR_NOPALETTEATTACHED;
897 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
898 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
899 IDirectDrawPalette));
900 return DD_OK;
903 HRESULT WINAPI
904 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
905 LPDDPIXELFORMAT pDDPixelFormat)
907 /* What is DDERR_INVALIDSURFACETYPE for here? */
908 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
910 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
911 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
912 return DD_OK;
915 HRESULT WINAPI
916 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
917 LPDWORD pdwPriority)
919 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
921 TRACE("(%p)->(%p)\n",This,pdwPriority);
922 CHECK_TEXTURE(This);
924 *pdwPriority = This->priority;
925 return DD_OK;
928 HRESULT WINAPI
929 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
930 REFGUID tag, LPVOID pBuffer,
931 LPDWORD pcbBufferSize)
933 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
934 PrivateData* data;
936 data = find_private_data(This, tag);
937 if (data == NULL) return DDERR_NOTFOUND;
939 /* This may not be right. */
940 if ((data->flags & DDSPD_VOLATILE)
941 && data->uniqueness_value != This->uniqueness_value)
942 return DDERR_EXPIRED;
944 if (*pcbBufferSize < data->size)
946 *pcbBufferSize = data->size;
947 return DDERR_MOREDATA;
950 if (data->flags & DDSPD_IUNKNOWNPTR)
952 *(LPUNKNOWN *)pBuffer = data->ptr.object;
953 IUnknown_AddRef(data->ptr.object);
955 else
957 memcpy(pBuffer, data->ptr.data, data->size);
960 return DD_OK;
963 HRESULT WINAPI
964 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
965 LPDDSURFACEDESC2 pDDSD)
967 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
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;
976 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
977 if (TRACE_ON(ddraw)) {
978 DDRAW_dump_surface_desc(pDDSD);
980 return DD_OK;
983 HRESULT WINAPI
984 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
985 LPDWORD pValue)
987 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
989 TRACE("(%p)->(%p)\n",This,pValue);
990 *pValue = This->uniqueness_value;
991 return DD_OK;
994 HRESULT WINAPI
995 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
996 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
998 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
999 return DDERR_ALREADYINITIALIZED;
1002 HRESULT WINAPI
1003 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
1005 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1007 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
1008 return This->lost ? DDERR_SURFACELOST : DD_OK;
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)
1018 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
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);
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));
1030 /* First, copy the Surface description */
1031 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
1033 /* Used to optimize the D3D Device locking */
1034 This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
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;
1057 This->lock_update(This, prect, flags);
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);
1066 TRACE("locked surface returning description : \n");
1067 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
1069 return DD_OK;
1072 HRESULT WINAPI
1073 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1075 /* Some surface types should return DDERR_CANTPAGELOCK. */
1076 return DD_OK;
1079 HRESULT WINAPI
1080 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
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;
1087 HRESULT WINAPI
1088 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1090 HRESULT hr;
1091 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1093 TRACE("(%p)->(%p)\n",This,hDC);
1095 if (!This->dc_in_use || This->hDC != hDC)
1096 return DDERR_INVALIDPARAMS;
1098 This->release_dc(This, hDC);
1100 hr = IDirectDrawSurface7_Unlock(iface, NULL);
1101 if (FAILED(hr)) return hr;
1103 This->dc_in_use = FALSE;
1104 This->hDC = 0;
1106 return DD_OK;
1109 /* Restore */
1111 HRESULT WINAPI
1112 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
1113 LPDIRECTDRAWCLIPPER pDDClipper)
1115 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1117 TRACE("(%p)->(%p)\n",This,pDDClipper);
1118 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
1119 return DD_OK;
1121 if (This->clipper != NULL)
1122 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1123 IDirectDrawClipper));
1125 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1126 pDDClipper);
1127 if (pDDClipper != NULL)
1128 IDirectDrawClipper_AddRef(pDDClipper);
1130 return DD_OK;
1133 HRESULT WINAPI
1134 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
1135 DWORD dwFlags, LPDDCOLORKEY pCKey)
1137 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1139 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
1141 if (TRACE_ON(ddraw)) {
1142 TRACE(" - colorkey flags : ");
1143 DDRAW_dump_colorkeyflag(dwFlags);
1146 if ((dwFlags & DDCKEY_COLORSPACE) != 0) {
1147 FIXME(" colorkey value not supported (%08lx) !\n", dwFlags);
1148 return DDERR_INVALIDPARAMS;
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).
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;
1162 case DDCKEY_DESTOVERLAY:
1163 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1164 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1165 break;
1167 case DDCKEY_SRCOVERLAY:
1168 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1169 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1170 break;
1172 case DDCKEY_SRCBLT:
1173 This->surface_desc.ddckCKSrcBlt = *pCKey;
1174 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
1175 break;
1177 default:
1178 return DDERR_INVALIDPARAMS;
1180 } else {
1181 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1182 case DDCKEY_DESTBLT:
1183 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
1184 break;
1186 case DDCKEY_DESTOVERLAY:
1187 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
1188 break;
1190 case DDCKEY_SRCOVERLAY:
1191 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
1192 break;
1194 case DDCKEY_SRCBLT:
1195 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
1196 break;
1198 default:
1199 return DDERR_INVALIDPARAMS;
1203 if (This->aux_setcolorkey_cb) This->aux_setcolorkey_cb(This, dwFlags, pCKey);
1205 return DD_OK;
1208 HRESULT WINAPI
1209 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1211 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1213 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1214 CHECK_TEXTURE(This);
1216 This->max_lod = dwMaxLOD;
1217 return DD_OK;
1220 HRESULT WINAPI
1221 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1222 LONG X, LONG Y)
1224 return DDERR_NOTAOVERLAYSURFACE;
1227 HRESULT WINAPI
1228 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1229 LPDIRECTDRAWPALETTE pPalette)
1231 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1232 IDirectDrawPalette *pal_to_rel = NULL;
1234 TRACE("(%p)->(%p)\n",This,pPalette);
1235 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1236 return DD_OK;
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);
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;
1252 This->set_palette(This, This->palette);
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.
1257 if (pal_to_rel != NULL)
1258 IDirectDrawPalette_Release(pal_to_rel);
1260 return DD_OK;
1263 HRESULT WINAPI
1264 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1265 DWORD dwPriority)
1267 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1269 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1270 CHECK_TEXTURE(This);
1272 This->priority = dwPriority;
1273 return DD_OK;
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)
1283 PrivateData* data;
1284 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1286 data = find_private_data(This, tag);
1287 if (data == NULL)
1289 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1290 if (data == NULL) return DDERR_OUTOFMEMORY;
1292 data->tag = *tag;
1293 data->flags = dwFlags;
1294 data->uniqueness_value = This->uniqueness_value;
1296 if (dwFlags & DDSPD_IUNKNOWNPTR)
1298 data->ptr.object = (LPUNKNOWN)pData;
1299 data->size = sizeof(LPUNKNOWN);
1300 IUnknown_AddRef(data->ptr.object);
1302 else
1304 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1305 if (data->ptr.data == NULL)
1307 HeapFree(GetProcessHeap(), 0, data);
1308 return DDERR_OUTOFMEMORY;
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;
1319 return DD_OK;
1321 else
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. */
1328 return E_FAIL;
1332 /* SetSurfaceDesc */
1334 HRESULT WINAPI
1335 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1337 ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1339 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1341 This->unlock_update(This, pRect);
1342 if (This->aux_unlock)
1343 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1345 return DD_OK;
1348 HRESULT WINAPI
1349 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1350 LPRECT pSrcRect,
1351 LPDIRECTDRAWSURFACE7 pDstSurface,
1352 LPRECT pDstRect, DWORD dwFlags,
1353 LPDDOVERLAYFX pFX)
1355 return DDERR_UNSUPPORTED;
1358 /* MSDN: "not currently implemented." */
1359 HRESULT WINAPI
1360 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1361 DWORD dwFlags)
1363 return DDERR_UNSUPPORTED;
1366 HRESULT WINAPI
1367 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1368 DWORD dwFlags,
1369 LPDIRECTDRAWSURFACE7 pDDSRef)
1371 return DDERR_NOTAOVERLAYSURFACE;