setupapi: Improve parameter validation for SetupCreateDiskSpaceListA/W.
[wine] / dlls / d3d9 / buffer.c
1 /*
2  * Copyright 2002-2004 Jason Edmeades
3  * Copyright 2002-2004 Raphael Junqueira
4  * Copyright 2005 Oliver Stieber
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "d3d9_private.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
25
26 static HRESULT WINAPI d3d9_vertexbuffer_QueryInterface(IDirect3DVertexBuffer9 *iface, REFIID riid, void **object)
27 {
28     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
29
30     if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer9)
31             || IsEqualGUID(riid, &IID_IDirect3DResource9)
32             || IsEqualGUID(riid, &IID_IUnknown))
33     {
34         IDirect3DVertexBuffer9_AddRef(iface);
35         *object = iface;
36         return S_OK;
37     }
38
39     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
40
41     *object = NULL;
42     return E_NOINTERFACE;
43 }
44
45 static ULONG WINAPI d3d9_vertexbuffer_AddRef(IDirect3DVertexBuffer9 *iface)
46 {
47     IDirect3DVertexBuffer9Impl *buffer = (IDirect3DVertexBuffer9Impl *)iface;
48     ULONG refcount = InterlockedIncrement(&buffer->ref);
49
50     TRACE("%p increasing refcount to %u.\n", iface, refcount);
51
52     if (refcount == 1)
53     {
54         IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
55         wined3d_mutex_lock();
56         IWineD3DBuffer_AddRef(buffer->wineD3DVertexBuffer);
57         wined3d_mutex_unlock();
58     }
59
60     return refcount;
61 }
62
63 static ULONG WINAPI d3d9_vertexbuffer_Release(IDirect3DVertexBuffer9 *iface)
64 {
65     IDirect3DVertexBuffer9Impl *buffer = (IDirect3DVertexBuffer9Impl *)iface;
66     ULONG refcount = InterlockedDecrement(&buffer->ref);
67
68     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
69
70     if (!refcount)
71     {
72         IDirect3DDevice9Ex *device = buffer->parentDevice;
73
74         wined3d_mutex_lock();
75         IWineD3DBuffer_Release(buffer->wineD3DVertexBuffer);
76         wined3d_mutex_unlock();
77
78         /* Release the device last, as it may cause the device to be destroyed. */
79         IDirect3DDevice9Ex_Release(device);
80     }
81
82     return refcount;
83 }
84
85 static HRESULT WINAPI d3d9_vertexbuffer_GetDevice(IDirect3DVertexBuffer9 *iface, IDirect3DDevice9 **device)
86 {
87     TRACE("iface %p, device %p.\n", iface, device);
88
89     *device = (IDirect3DDevice9 *)((IDirect3DVertexBuffer9Impl *)iface)->parentDevice;
90     IDirect3DDevice9_AddRef(*device);
91
92     TRACE("Returning device %p.\n", *device);
93
94     return D3D_OK;
95 }
96
97 static HRESULT WINAPI d3d9_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer9 *iface,
98         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
99 {
100     HRESULT hr;
101
102     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
103             iface, debugstr_guid(guid), data, data_size, flags);
104
105     wined3d_mutex_lock();
106     hr = IWineD3DBuffer_SetPrivateData(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer,
107             guid, data, data_size, flags);
108     wined3d_mutex_unlock();
109
110     return hr;
111 }
112
113 static HRESULT WINAPI d3d9_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer9 *iface,
114         REFGUID guid, void *data, DWORD *data_size)
115 {
116     HRESULT hr;
117
118     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
119             iface, debugstr_guid(guid), data, data_size);
120
121     wined3d_mutex_lock();
122     hr = IWineD3DBuffer_GetPrivateData(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer,
123             guid, data, data_size);
124     wined3d_mutex_unlock();
125
126     return hr;
127 }
128
129 static HRESULT WINAPI d3d9_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer9 *iface, REFGUID guid)
130 {
131     HRESULT hr;
132
133     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
134
135     wined3d_mutex_lock();
136     hr = IWineD3DBuffer_FreePrivateData(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer, guid);
137     wined3d_mutex_unlock();
138
139     return hr;
140 }
141
142 static DWORD WINAPI d3d9_vertexbuffer_SetPriority(IDirect3DVertexBuffer9 *iface, DWORD priority)
143 {
144     DWORD previous;
145
146     TRACE("iface %p, priority %u.\n", iface, priority);
147
148     wined3d_mutex_lock();
149     previous = IWineD3DBuffer_SetPriority(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer, priority);
150     wined3d_mutex_unlock();
151
152     return previous;
153 }
154
155 static DWORD WINAPI d3d9_vertexbuffer_GetPriority(IDirect3DVertexBuffer9 *iface)
156 {
157     DWORD priority;
158
159     TRACE("iface %p.\n", iface);
160
161     wined3d_mutex_lock();
162     priority = IWineD3DBuffer_GetPriority(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer);
163     wined3d_mutex_unlock();
164
165     return priority;
166 }
167
168 static void WINAPI d3d9_vertexbuffer_PreLoad(IDirect3DVertexBuffer9 *iface)
169 {
170     TRACE("iface %p.\n", iface);
171
172     wined3d_mutex_lock();
173     IWineD3DBuffer_PreLoad(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer);
174     wined3d_mutex_unlock();
175 }
176
177 static D3DRESOURCETYPE WINAPI d3d9_vertexbuffer_GetType(IDirect3DVertexBuffer9 *iface)
178 {
179     TRACE("iface %p.\n", iface);
180
181     return D3DRTYPE_VERTEXBUFFER;
182 }
183
184 static HRESULT WINAPI d3d9_vertexbuffer_Lock(IDirect3DVertexBuffer9 *iface,
185         UINT offset, UINT size, void **data, DWORD flags)
186 {
187     HRESULT hr;
188
189     TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
190             iface, offset, size, data, flags);
191
192     wined3d_mutex_lock();
193     hr = IWineD3DBuffer_Map(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer,
194             offset, size, (BYTE **)data, flags);
195     wined3d_mutex_unlock();
196
197     return hr;
198 }
199
200 static HRESULT WINAPI d3d9_vertexbuffer_Unlock(IDirect3DVertexBuffer9 *iface)
201 {
202     HRESULT hr;
203
204     TRACE("iface %p.\n", iface);
205
206     wined3d_mutex_lock();
207     hr = IWineD3DBuffer_Unmap(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer);
208     wined3d_mutex_unlock();
209
210     return hr;
211 }
212
213 static HRESULT WINAPI d3d9_vertexbuffer_GetDesc(IDirect3DVertexBuffer9 *iface, D3DVERTEXBUFFER_DESC *desc)
214 {
215     IDirect3DVertexBuffer9Impl *buffer = (IDirect3DVertexBuffer9Impl *)iface;
216     WINED3DBUFFER_DESC wined3d_desc;
217     HRESULT hr;
218
219     TRACE("iface %p, desc %p.\n", iface, desc);
220
221     wined3d_mutex_lock();
222     hr = IWineD3DBuffer_GetDesc(buffer->wineD3DVertexBuffer, &wined3d_desc);
223     wined3d_mutex_unlock();
224
225     if (SUCCEEDED(hr))
226     {
227         desc->Format = D3DFMT_VERTEXDATA;
228         desc->Usage = wined3d_desc.Usage;
229         desc->Pool = wined3d_desc.Pool;
230         desc->Size = wined3d_desc.Size;
231         desc->Type = D3DRTYPE_VERTEXBUFFER;
232         desc->FVF = buffer->fvf;
233     }
234
235     return hr;
236 }
237
238 static const IDirect3DVertexBuffer9Vtbl d3d9_vertexbuffer_vtbl =
239 {
240     /* IUnknown */
241     d3d9_vertexbuffer_QueryInterface,
242     d3d9_vertexbuffer_AddRef,
243     d3d9_vertexbuffer_Release,
244     /* IDirect3DResource9 */
245     d3d9_vertexbuffer_GetDevice,
246     d3d9_vertexbuffer_SetPrivateData,
247     d3d9_vertexbuffer_GetPrivateData,
248     d3d9_vertexbuffer_FreePrivateData,
249     d3d9_vertexbuffer_SetPriority,
250     d3d9_vertexbuffer_GetPriority,
251     d3d9_vertexbuffer_PreLoad,
252     d3d9_vertexbuffer_GetType,
253     /* IDirect3DVertexBuffer9 */
254     d3d9_vertexbuffer_Lock,
255     d3d9_vertexbuffer_Unlock,
256     d3d9_vertexbuffer_GetDesc,
257 };
258
259 static void STDMETHODCALLTYPE d3d9_vertexbuffer_wined3d_object_destroyed(void *parent)
260 {
261     HeapFree(GetProcessHeap(), 0, parent);
262 }
263
264 static const struct wined3d_parent_ops d3d9_vertexbuffer_wined3d_parent_ops =
265 {
266     d3d9_vertexbuffer_wined3d_object_destroyed,
267 };
268
269 HRESULT vertexbuffer_init(IDirect3DVertexBuffer9Impl *buffer, IDirect3DDevice9Impl *device,
270         UINT size, UINT usage, DWORD fvf, D3DPOOL pool)
271 {
272     HRESULT hr;
273
274     buffer->lpVtbl = &d3d9_vertexbuffer_vtbl;
275     buffer->ref = 1;
276     buffer->fvf = fvf;
277
278     wined3d_mutex_lock();
279     hr = IWineD3DDevice_CreateVertexBuffer(device->WineD3DDevice, size, usage & WINED3DUSAGE_MASK,
280             (WINED3DPOOL)pool, buffer, &d3d9_vertexbuffer_wined3d_parent_ops, &buffer->wineD3DVertexBuffer);
281     wined3d_mutex_unlock();
282     if (FAILED(hr))
283     {
284         WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
285         return hr;
286     }
287
288     buffer->parentDevice = (IDirect3DDevice9Ex *)device;
289     IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
290
291     return D3D_OK;
292 }
293
294 static HRESULT WINAPI d3d9_indexbuffer_QueryInterface(IDirect3DIndexBuffer9 *iface, REFIID riid, void **object)
295 {
296     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
297
298     if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer9)
299             || IsEqualGUID(riid, &IID_IDirect3DResource9)
300             || IsEqualGUID(riid, &IID_IUnknown))
301     {
302         IDirect3DIndexBuffer9_AddRef(iface);
303         *object = iface;
304         return S_OK;
305     }
306
307     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
308
309     *object = NULL;
310     return E_NOINTERFACE;
311 }
312
313 static ULONG WINAPI d3d9_indexbuffer_AddRef(IDirect3DIndexBuffer9 *iface)
314 {
315     IDirect3DIndexBuffer9Impl *buffer = (IDirect3DIndexBuffer9Impl *)iface;
316     ULONG refcount = InterlockedIncrement(&buffer->ref);
317
318     TRACE("%p increasing refcount to %u.\n", iface, refcount);
319
320     if (refcount == 1)
321     {
322         IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
323         wined3d_mutex_lock();
324         IWineD3DBuffer_AddRef(buffer->wineD3DIndexBuffer);
325         wined3d_mutex_unlock();
326     }
327
328     return refcount;
329 }
330
331 static ULONG WINAPI d3d9_indexbuffer_Release(IDirect3DIndexBuffer9 *iface)
332 {
333     IDirect3DIndexBuffer9Impl *buffer = (IDirect3DIndexBuffer9Impl *)iface;
334     ULONG refcount = InterlockedDecrement(&buffer->ref);
335
336     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
337
338     if (!refcount)
339     {
340         IDirect3DDevice9Ex *device = buffer->parentDevice;
341
342         wined3d_mutex_lock();
343         IWineD3DBuffer_Release(buffer->wineD3DIndexBuffer);
344         wined3d_mutex_unlock();
345
346         /* Release the device last, as it may cause the device to be destroyed. */
347         IDirect3DDevice9Ex_Release(device);
348     }
349
350     return refcount;
351 }
352
353 static HRESULT WINAPI d3d9_indexbuffer_GetDevice(IDirect3DIndexBuffer9 *iface, IDirect3DDevice9 **device)
354 {
355     TRACE("iface %p, device %p.\n", iface, device);
356
357     *device = (IDirect3DDevice9 *)((IDirect3DIndexBuffer9Impl *)iface)->parentDevice;
358     IDirect3DDevice9_AddRef(*device);
359
360     TRACE("Returning device %p.\n", *device);
361
362     return D3D_OK;
363 }
364
365 static HRESULT WINAPI d3d9_indexbuffer_SetPrivateData(IDirect3DIndexBuffer9 *iface,
366         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
367 {
368     HRESULT hr;
369
370     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
371             iface, debugstr_guid(guid), data, data_size, flags);
372
373     wined3d_mutex_lock();
374     hr = IWineD3DBuffer_SetPrivateData(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer,
375             guid, data, data_size, flags);
376     wined3d_mutex_unlock();
377
378     return hr;
379 }
380
381 static HRESULT WINAPI d3d9_indexbuffer_GetPrivateData(IDirect3DIndexBuffer9 *iface,
382         REFGUID guid, void *data, DWORD *data_size)
383 {
384     HRESULT hr;
385
386     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
387             iface, debugstr_guid(guid), data, data_size);
388
389     wined3d_mutex_lock();
390     hr = IWineD3DBuffer_GetPrivateData(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer,
391             guid, data, data_size);
392     wined3d_mutex_unlock();
393
394     return hr;
395 }
396
397 static HRESULT WINAPI d3d9_indexbuffer_FreePrivateData(IDirect3DIndexBuffer9 *iface, REFGUID guid)
398 {
399     HRESULT hr;
400
401     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
402
403     wined3d_mutex_lock();
404     hr = IWineD3DBuffer_FreePrivateData(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer, guid);
405     wined3d_mutex_unlock();
406
407     return hr;
408 }
409
410 static DWORD WINAPI d3d9_indexbuffer_SetPriority(IDirect3DIndexBuffer9 *iface, DWORD priority)
411 {
412     DWORD previous;
413
414     TRACE("iface %p, priority %u.\n", iface, priority);
415
416     wined3d_mutex_lock();
417     previous = IWineD3DBuffer_SetPriority(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer, priority);
418     wined3d_mutex_unlock();
419
420     return previous;
421 }
422
423 static DWORD WINAPI d3d9_indexbuffer_GetPriority(IDirect3DIndexBuffer9 *iface)
424 {
425     DWORD priority;
426
427     TRACE("iface %p.\n", iface);
428
429     wined3d_mutex_lock();
430     priority = IWineD3DBuffer_GetPriority(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer);
431     wined3d_mutex_unlock();
432
433     return priority;
434 }
435
436 static void WINAPI d3d9_indexbuffer_PreLoad(IDirect3DIndexBuffer9 *iface)
437 {
438     TRACE("iface %p.\n", iface);
439
440     wined3d_mutex_lock();
441     IWineD3DBuffer_PreLoad(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer);
442     wined3d_mutex_unlock();
443 }
444
445 static D3DRESOURCETYPE WINAPI d3d9_indexbuffer_GetType(IDirect3DIndexBuffer9 *iface)
446 {
447     TRACE("iface %p.\n", iface);
448
449     return D3DRTYPE_INDEXBUFFER;
450 }
451
452 static HRESULT WINAPI d3d9_indexbuffer_Lock(IDirect3DIndexBuffer9 *iface,
453         UINT offset, UINT size, void **data, DWORD flags)
454 {
455     HRESULT hr;
456
457     TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
458             iface, offset, size, data, flags);
459
460     wined3d_mutex_lock();
461     hr = IWineD3DBuffer_Map(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer,
462             offset, size, (BYTE **)data, flags);
463     wined3d_mutex_unlock();
464
465     return hr;
466 }
467
468 static HRESULT WINAPI d3d9_indexbuffer_Unlock(IDirect3DIndexBuffer9 *iface)
469 {
470     HRESULT hr;
471
472     TRACE("iface %p.\n", iface);
473
474     wined3d_mutex_lock();
475     hr = IWineD3DBuffer_Unmap(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer);
476     wined3d_mutex_unlock();
477
478     return hr;
479 }
480
481 static HRESULT WINAPI d3d9_indexbuffer_GetDesc(IDirect3DIndexBuffer9 *iface, D3DINDEXBUFFER_DESC *desc)
482 {
483     IDirect3DIndexBuffer9Impl *buffer = (IDirect3DIndexBuffer9Impl *)iface;
484     WINED3DBUFFER_DESC wined3d_desc;
485     HRESULT hr;
486
487     TRACE("iface %p, desc %p.\n", iface, desc);
488
489     wined3d_mutex_lock();
490     hr = IWineD3DBuffer_GetDesc(buffer->wineD3DIndexBuffer, &wined3d_desc);
491     wined3d_mutex_unlock();
492
493     if (SUCCEEDED(hr))
494     {
495         desc->Format = d3dformat_from_wined3dformat(buffer->format);
496         desc->Usage = wined3d_desc.Usage;
497         desc->Pool = wined3d_desc.Pool;
498         desc->Size = wined3d_desc.Size;
499         desc->Type = D3DRTYPE_INDEXBUFFER;
500     }
501
502     return hr;
503 }
504
505 static const IDirect3DIndexBuffer9Vtbl d3d9_indexbuffer_vtbl =
506 {
507     /* IUnknown */
508     d3d9_indexbuffer_QueryInterface,
509     d3d9_indexbuffer_AddRef,
510     d3d9_indexbuffer_Release,
511     /* IDirect3DResource9 */
512     d3d9_indexbuffer_GetDevice,
513     d3d9_indexbuffer_SetPrivateData,
514     d3d9_indexbuffer_GetPrivateData,
515     d3d9_indexbuffer_FreePrivateData,
516     d3d9_indexbuffer_SetPriority,
517     d3d9_indexbuffer_GetPriority,
518     d3d9_indexbuffer_PreLoad,
519     d3d9_indexbuffer_GetType,
520     /* IDirect3DIndexBuffer9 */
521     d3d9_indexbuffer_Lock,
522     d3d9_indexbuffer_Unlock,
523     d3d9_indexbuffer_GetDesc,
524 };
525
526 static void STDMETHODCALLTYPE d3d9_indexbuffer_wined3d_object_destroyed(void *parent)
527 {
528     HeapFree(GetProcessHeap(), 0, parent);
529 }
530
531 static const struct wined3d_parent_ops d3d9_indexbuffer_wined3d_parent_ops =
532 {
533     d3d9_indexbuffer_wined3d_object_destroyed,
534 };
535
536 HRESULT indexbuffer_init(IDirect3DIndexBuffer9Impl *buffer, IDirect3DDevice9Impl *device,
537         UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
538 {
539     HRESULT hr;
540
541     buffer->lpVtbl = &d3d9_indexbuffer_vtbl;
542     buffer->ref = 1;
543     buffer->format = wined3dformat_from_d3dformat(format);
544
545     wined3d_mutex_lock();
546     hr = IWineD3DDevice_CreateIndexBuffer(device->WineD3DDevice, size, usage & WINED3DUSAGE_MASK,
547             (WINED3DPOOL)pool, buffer, &d3d9_indexbuffer_wined3d_parent_ops, &buffer->wineD3DIndexBuffer);
548     wined3d_mutex_unlock();
549     if (FAILED(hr))
550     {
551         WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
552         return hr;
553     }
554
555     buffer->parentDevice = (IDirect3DDevice9Ex *)device;
556     IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
557
558     return D3D_OK;
559 }