ole32: Fix memory leaks in the storage test.
[wine] / dlls / ddrawex / tests / surface.c
1 /*
2  * Unit tests for ddrawex surfaces
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 #define COBJMACROS
19 /* For IID_IDirectDraw3 - it is not in dxguid.dll */
20 #define INITGUID
21
22 #include <assert.h>
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "ddraw.h"
27 #include "ddrawex.h"
28 #include "unknwn.h"
29
30 static IDirectDrawFactory *factory;
31 static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
32
33 static IDirectDraw *createDD(void)
34 {
35     HRESULT hr;
36     IDirectDraw *dd;
37
38     hr = IDirectDrawFactory_CreateDirectDraw(factory, NULL, NULL, DDSCL_NORMAL, 0,
39                                              0, &dd);
40     ok(hr == DD_OK, "Failed to create an IDirectDraw interface, hr = 0x%08x\n", hr);
41     return SUCCEEDED(hr) ? dd : NULL;
42 }
43
44 static void dctest_surf(IDirectDrawSurface *surf, int ddsdver) {
45     HRESULT hr;
46     HDC dc, dc2 = (HDC) 0x1234;
47     DDSURFACEDESC ddsd;
48     DDSURFACEDESC2 ddsd2;
49
50     memset(&ddsd, 0, sizeof(ddsd));
51     ddsd.dwSize = sizeof(ddsd);
52     memset(&ddsd2, 0, sizeof(ddsd2));
53     ddsd2.dwSize = sizeof(ddsd2);
54
55     hr = IDirectDrawSurface_GetDC(surf, &dc);
56     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
57
58     hr = IDirectDrawSurface_GetDC(surf, &dc);
59     ok(hr == DDERR_DCALREADYCREATED, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
60     ok(dc2 == (HDC) 0x1234, "The failed GetDC call changed the dc: %p\n", dc2);
61
62     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
63     ok(hr == DDERR_SURFACEBUSY, "IDirectDrawSurface_Lock returned 0x%08x, expected DDERR_SURFACEBUSY\n", hr);
64
65     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
66     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
67     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
68     ok(hr == DDERR_NODC, "IDirectDrawSurface_ReleaseDC returned 0x%08x, expected DDERR_NODC\n", hr);
69 }
70
71 static void GetDCTest_main(DDSURFACEDESC *ddsd, DDSURFACEDESC2 *ddsd2, void (*testfunc)(IDirectDrawSurface *surf, int ddsdver))
72 {
73     IDirectDrawSurface *surf;
74     IDirectDrawSurface2 *surf2;
75     IDirectDrawSurface2 *surf3;
76     IDirectDrawSurface4 *surf4;
77     HRESULT hr;
78     IDirectDraw  *dd1 = createDD();
79     IDirectDraw2 *dd2;
80     IDirectDraw3 *dd3;
81     IDirectDraw4 *dd4;
82
83     hr = IDirectDraw_CreateSurface(dd1, ddsd, &surf, NULL);
84     if (hr == DDERR_UNSUPPORTEDMODE) {
85         win_skip("Unsupported mode\n");
86         return;
87     }
88     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
89     testfunc(surf, 1);
90     IDirectDrawSurface_Release(surf);
91
92     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirectDraw2, (void **) &dd2);
93     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
94
95     hr = IDirectDraw2_CreateSurface(dd2, ddsd, &surf, NULL);
96     ok(hr == DD_OK, "IDirectDraw2_CreateSurface failed: 0x%08x\n", hr);
97     testfunc(surf, 1);
98
99     hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2);
100     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed: 0x%08x\n", hr);
101     testfunc((IDirectDrawSurface *) surf2, 1);
102
103     IDirectDrawSurface2_Release(surf2);
104     IDirectDrawSurface_Release(surf);
105     IDirectDraw2_Release(dd2);
106
107     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirectDraw3, (void **) &dd3);
108     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
109
110     hr = IDirectDraw3_CreateSurface(dd3, ddsd, &surf, NULL);
111     ok(hr == DD_OK, "IDirectDraw3_CreateSurface failed: 0x%08x\n", hr);
112     testfunc(surf, 1);
113
114     hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface3, (void **) &surf3);
115     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed: 0x%08x\n", hr);
116     testfunc((IDirectDrawSurface *) surf3, 1);
117
118     IDirectDrawSurface3_Release(surf3);
119     IDirectDrawSurface_Release(surf);
120     IDirectDraw3_Release(dd3);
121
122     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirectDraw4, (void **) &dd4);
123     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
124
125     surf = NULL;
126     hr = IDirectDraw4_CreateSurface(dd4, ddsd2, &surf4, NULL);
127     ok(hr == DD_OK, "IDirectDraw4_CreateSurface failed: 0x%08x\n", hr);
128     testfunc((IDirectDrawSurface *) surf4, 2);
129
130     IDirectDrawSurface4_Release(surf4);
131     IDirectDraw4_Release(dd4);
132
133     IDirectDraw_Release(dd1);
134 }
135
136 static void GetDCTest(void)
137 {
138     DDSURFACEDESC ddsd;
139     DDSURFACEDESC2 ddsd2;
140
141     memset(&ddsd, 0, sizeof(ddsd));
142     ddsd.dwSize = sizeof(ddsd);
143     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
144     ddsd.dwWidth = 64;
145     ddsd.dwHeight = 64;
146     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
147     memset(&ddsd2, 0, sizeof(ddsd2));
148     ddsd2.dwSize = sizeof(ddsd2);
149     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
150     ddsd2.dwWidth = 64;
151     ddsd2.dwHeight = 64;
152     ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
153
154     GetDCTest_main(&ddsd, &ddsd2, dctest_surf);
155 }
156
157 static void CapsTest(void)
158 {
159     DDSURFACEDESC ddsd;
160     IDirectDraw  *dd1 = createDD();
161     IDirectDrawSurface *surf;
162     HRESULT hr;
163
164     memset(&ddsd, 0, sizeof(ddsd));
165     ddsd.dwSize = sizeof(ddsd);
166     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
167     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
168     ddsd.dwWidth = 64;
169     ddsd.dwHeight = 64;
170     hr = IDirectDraw_CreateSurface(dd1, &ddsd, &surf, NULL);
171     if (hr == DDERR_UNSUPPORTEDMODE) {
172         win_skip("Unsupported mode\n");
173         return;
174     }
175     ok(hr == DD_OK, "Creating a SYSMEM | VIDMEM surface returned 0x%08x, expected DD_OK\n", hr);
176     if(surf) IDirectDrawSurface_Release(surf);
177
178     IDirectDraw_Release(dd1);
179 }
180
181 static void dctest_sysvidmem(IDirectDrawSurface *surf, int ddsdver) {
182     HRESULT hr;
183     HDC dc, dc2 = (HDC) 0x1234;
184     DDSURFACEDESC ddsd;
185     DDSURFACEDESC2 ddsd2;
186
187     memset(&ddsd, 0, sizeof(ddsd));
188     ddsd.dwSize = sizeof(ddsd);
189     memset(&ddsd2, 0, sizeof(ddsd2));
190     ddsd2.dwSize = sizeof(ddsd2);
191
192     hr = IDirectDrawSurface_GetDC(surf, &dc);
193     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
194
195     hr = IDirectDrawSurface_GetDC(surf, &dc2);
196     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
197     ok(dc == dc2, "Got two different DCs\n");
198
199     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
200     ok(hr == DD_OK, "IDirectDrawSurface_Lock returned 0x%08x, expected DD_OK\n", hr);
201
202     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
203     ok(hr == DDERR_SURFACEBUSY, "IDirectDrawSurface_Lock returned 0x%08x, expected DDERR_SURFACEBUSY\n", hr);
204
205     hr = IDirectDrawSurface_Unlock(surf, NULL);
206     ok(hr == DD_OK, "IDirectDrawSurface_Unlock returned 0x%08x, expected DD_OK\n", hr);
207     hr = IDirectDrawSurface_Unlock(surf, NULL);
208     ok(hr == DDERR_NOTLOCKED, "IDirectDrawSurface_Unlock returned 0x%08x, expected DDERR_NOTLOCKED\n", hr);
209
210     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
211     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
212     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
213     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
214     /* That works any number of times... */
215     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
216     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
217 }
218
219 static void SysVidMemTest(void)
220 {
221     DDSURFACEDESC ddsd;
222     DDSURFACEDESC2 ddsd2;
223
224     memset(&ddsd, 0, sizeof(ddsd));
225     ddsd.dwSize = sizeof(ddsd);
226     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
227     ddsd.dwWidth = 64;
228     ddsd.dwHeight = 64;
229     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
230     memset(&ddsd2, 0, sizeof(ddsd2));
231     ddsd2.dwSize = sizeof(ddsd2);
232     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
233     ddsd2.dwWidth = 64;
234     ddsd2.dwHeight = 64;
235     ddsd2.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
236
237     GetDCTest_main(&ddsd, &ddsd2, dctest_sysvidmem);
238 }
239
240 START_TEST(surface)
241 {
242     IClassFactory *classfactory = NULL;
243     ULONG ref;
244     HRESULT hr;
245     HMODULE hmod = LoadLibrary("ddrawex.dll");
246     if(hmod == NULL) {
247         skip("Failed to load ddrawex.dll\n");
248         return;
249     }
250     pDllGetClassObject = (void*)GetProcAddress(hmod, "DllGetClassObject");
251     if(pDllGetClassObject == NULL) {
252         skip("Failed to get DllGetClassObject\n");
253         return;
254     }
255
256     hr = pDllGetClassObject(&CLSID_DirectDrawFactory, &IID_IClassFactory, (void **) &classfactory);
257     ok(hr == S_OK, "Failed to create a IClassFactory\n");
258     hr = IClassFactory_CreateInstance(classfactory, NULL, &IID_IDirectDrawFactory, (void **) &factory);
259     ok(hr == S_OK, "Failed to create a IDirectDrawFactory\n");
260
261     GetDCTest();
262     CapsTest();
263     SysVidMemTest();
264
265     if(factory) {
266         ref = IDirectDrawFactory_Release(factory);
267         ok(ref == 0, "IDirectDrawFactory not cleanly released\n");
268     }
269     if(classfactory) {
270         ref = IClassFactory_Release(classfactory);
271         todo_wine ok(ref == 1, "IClassFactory refcount wrong, ref = %u\n", ref);
272     }
273 }