mshtml: COM cleanup for the IOleDocument iface.
[wine] / dlls / d3drm / meshbuilder.c
1 /*
2  * Implementation of IDirect3DRMMeshBuilder Interface
3  *
4  * Copyright 2010 Christian Costa
5  *
6  * This file contains the (internal) driver registration functions,
7  * driver enumeration APIs and DirectDraw creation functions.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "wine/debug.h"
25
26 #define COBJMACROS
27
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "dxfile.h"
31 #include "rmxfguid.h"
32
33 #include "d3drm_private.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(d3drm);
36
37 typedef struct {
38     D3DVALUE u;
39     D3DVALUE v;
40 } Coords2d;
41
42 typedef struct {
43     IDirect3DRMMeshBuilder IDirect3DRMMeshBuilder_iface;
44     LONG ref;
45     DWORD nb_vertices;
46     D3DVECTOR* pVertices;
47     DWORD nb_normals;
48     D3DVECTOR* pNormals;
49     DWORD nb_faces;
50     DWORD face_data_size;
51     LPVOID pFaceData;
52     DWORD nb_coords2d;
53     Coords2d* pCoords2d;
54 } IDirect3DRMMeshBuilderImpl;
55
56 typedef struct {
57     WORD major;
58     WORD minor;
59     DWORD flags;
60 } Header;
61
62 static const struct IDirect3DRMMeshBuilderVtbl Direct3DRMMeshBuilder_Vtbl;
63
64 static char templates[] = {
65 "xof 0302txt 0064"
66 "template Header"
67 "{"
68 "<3D82AB43-62DA-11CF-AB39-0020AF71E433>"
69 "WORD major;"
70 "WORD minor;"
71 "DWORD flags;"
72 "}"
73 "template Vector"
74 "{"
75 "<3D82AB5E-62DA-11CF-AB39-0020AF71E433>"
76 "FLOAT x;"
77 "FLOAT y;"
78 "FLOAT z;"
79 "}"
80 "template Coords2d"
81 "{"
82 "<F6F23F44-7686-11CF-8F52-0040333594A3>"
83 "FLOAT u;"
84 "FLOAT v;"
85 "}"
86 "template Matrix4x4"
87 "{"
88 "<F6F23F45-7686-11CF-8F52-0040333594A3>"
89 "array FLOAT matrix[16];"
90 "}"
91 "template ColorRGBA"
92 "{"
93 "<35FF44E0-6C7C-11CF-8F52-0040333594A3>"
94 "FLOAT red;"
95 "FLOAT green;"
96 "FLOAT blue;"
97 "FLOAT alpha;"
98 "}"
99 "template ColorRGB"
100 "{"
101 "<D3E16E81-7835-11CF-8F52-0040333594A3>"
102 "FLOAT red;"
103 "FLOAT green;"
104 "FLOAT blue;"
105 "}"
106 "template IndexedColor"
107 "{"
108 "<1630B820-7842-11CF-8F52-0040333594A3>"
109 "DWORD index;"
110 "ColorRGBA indexColor;"
111 "}"
112 "template Boolean"
113 "{"
114 "<537DA6A0-CA37-11D0-941C-0080C80CFA7B>"
115 "DWORD truefalse;"
116 "}"
117 "template Boolean2d"
118 "{"
119 "<4885AE63-78E8-11CF-8F52-0040333594A3>"
120 "Boolean u;"
121 "Boolean v;"
122 "}"
123 "template MaterialWrap"
124 "{"
125 "<4885AE60-78E8-11CF-8F52-0040333594A3>"
126 "Boolean u;"
127 "Boolean v;"
128 "}"
129 "template TextureFilename"
130 "{"
131 "<A42790E1-7810-11CF-8F52-0040333594A3>"
132 "STRING filename;"
133 "}"
134 "template Material"
135 "{"
136 "<3D82AB4D-62DA-11CF-AB39-0020AF71E433>"
137 "ColorRGBA faceColor;"
138 "FLOAT power;"
139 "ColorRGB specularColor;"
140 "ColorRGB emissiveColor;"
141 "[...]"
142 "}"
143 "template MeshFace"
144 "{"
145 "<3D82AB5F-62DA-11CF-AB39-0020AF71E433>"
146 "DWORD nFaceVertexIndices;"
147 "array DWORD faceVertexIndices[nFaceVertexIndices];"
148 "}"
149 "template MeshFaceWraps"
150 "{"
151 "<ED1EC5C0-C0A8-11D0-941C-0080C80CFA7B>"
152 "DWORD nFaceWrapValues;"
153 "array Boolean2d faceWrapValues[nFaceWrapValues];"
154 "}"
155 "template MeshTextureCoords"
156 "{"
157 "<F6F23F40-7686-11CF-8F52-0040333594A3>"
158 "DWORD nTextureCoords;"
159 "array Coords2d textureCoords[nTextureCoords];"
160 "}"
161 "template MeshMaterialList"
162 "{"
163 "<F6F23F42-7686-11CF-8F52-0040333594A3>"
164 "DWORD nMaterials;"
165 "DWORD nFaceIndexes;"
166 "array DWORD faceIndexes[nFaceIndexes];"
167 "[Material]"
168 "}"
169 "template MeshNormals"
170 "{"
171 "<F6F23F43-7686-11CF-8F52-0040333594A3>"
172 "DWORD nNormals;"
173 "array Vector normals[nNormals];"
174 "DWORD nFaceNormals;"
175 "array MeshFace faceNormals[nFaceNormals];"
176 "}"
177 "template MeshVertexColors"
178 "{"
179 "<1630B821-7842-11CF-8F52-0040333594A3>"
180 "DWORD nVertexColors;"
181 "array IndexedColor vertexColors[nVertexColors];"
182 "}"
183 "template Mesh"
184 "{"
185 "<3D82AB44-62DA-11CF-AB39-0020AF71E433>"
186 "DWORD nVertices;"
187 "array Vector vertices[nVertices];"
188 "DWORD nFaces;"
189 "array MeshFace faces[nFaces];"
190 "[...]"
191 "}"
192 "template FrameTransformMatrix"
193 "{"
194 "<F6F23F41-7686-11CF-8F52-0040333594A3>"
195 "Matrix4x4 frameMatrix;"
196 "}"
197 "template Frame"
198 "{"
199 "<3D82AB46-62DA-11CF-AB39-0020AF71E433>"
200 "[...]"
201 "}"
202 "template FloatKeys"
203 "{"
204 "<10DD46A9-775B-11CF-8F52-0040333594A3>"
205 "DWORD nValues;"
206 "array FLOAT values[nValues];"
207 "}"
208 "template TimedFloatKeys"
209 "{"
210 "<F406B180-7B3B-11CF-8F52-0040333594A3>"
211 "DWORD time;"
212 "FloatKeys tfkeys;"
213 "}"
214 "template AnimationKey"
215 "{"
216 "<10DD46A8-775B-11CF-8F52-0040333594A3>"
217 "DWORD keyType;"
218 "DWORD nKeys;"
219 "array TimedFloatKeys keys[nKeys];"
220 "}"
221 "template AnimationOptions"
222 "{"
223 "<E2BF56C0-840F-11CF-8F52-0040333594A3>"
224 "DWORD openclosed;"
225 "DWORD positionquality;"
226 "}"
227 "template Animation"
228 "{"
229 "<3D82AB4F-62DA-11CF-AB39-0020AF71E433>"
230 "[...]"
231 "}"
232 "template AnimationSet"
233 "{"
234 "<3D82AB50-62DA-11CF-AB39-0020AF71E433>"
235 "[Animation]"
236 "}"
237 "template InlineData"
238 "{"
239 "<3A23EEA0-94B1-11D0-AB39-0020AF71E433>"
240 "[BINARY]"
241 "}"
242 "template Url"
243 "{"
244 "<3A23EEA1-94B1-11D0-AB39-0020AF71E433>"
245 "DWORD nUrls;"
246 "array STRING urls[nUrls];"
247 "}"
248 "template ProgressiveMesh"
249 "{"
250 "<8A63C360-997D-11D0-941C-0080C80CFA7B>"
251 "[Url,InlineData]"
252 "}"
253 "template Guid"
254 "{"
255 "<A42790E0-7810-11CF-8F52-0040333594A3>"
256 "DWORD data1;"
257 "WORD data2;"
258 "WORD data3;"
259 "array UCHAR data4[8];"
260 "}"
261 "template StringProperty"
262 "{"
263 "<7F0F21E0-BFE1-11D1-82C0-00A0C9697271>"
264 "STRING key;"
265 "STRING value;"
266 "}"
267 "template PropertyBag"
268 "{"
269 "<7F0F21E1-BFE1-11D1-82C0-00A0C9697271>"
270 "[StringProperty]"
271 "}"
272 "template ExternalVisual"
273 "{"
274 "<98116AA0-BDBA-11D1-82C0-00A0C9697271>"
275 "Guid guidExternalVisual;"
276 "[...]"
277 "}"
278 "template RightHanded"
279 "{"
280 "<7F5D5EA0-D53A-11D1-82C0-00A0C9697271>"
281 "DWORD bRightHanded;"
282 "}"
283 };
284
285 static inline IDirect3DRMMeshBuilderImpl *impl_from_IDirect3DRMMeshBuilder(IDirect3DRMMeshBuilder *iface)
286 {
287     return CONTAINING_RECORD(iface, IDirect3DRMMeshBuilderImpl, IDirect3DRMMeshBuilder_iface);
288 }
289
290 HRESULT Direct3DRMMeshBuilder_create(LPDIRECT3DRMMESHBUILDER* ppMeshBuilder)
291 {
292     IDirect3DRMMeshBuilderImpl* object;
293
294     TRACE("(%p)\n", ppMeshBuilder);
295
296     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DRMMeshBuilderImpl));
297     if (!object)
298     {
299         ERR("Out of memory\n");
300         return E_OUTOFMEMORY;
301     }
302
303     object->IDirect3DRMMeshBuilder_iface.lpVtbl = &Direct3DRMMeshBuilder_Vtbl;
304     object->ref = 1;
305
306     *ppMeshBuilder = (IDirect3DRMMeshBuilder*)object;
307
308     return S_OK;
309 }
310
311 /*** IUnknown methods ***/
312 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_QueryInterface(IDirect3DRMMeshBuilder* iface, REFIID riid, void** ppvObject)
313 {
314     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
315
316     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
317
318     if (IsEqualGUID(riid, &IID_IUnknown) ||
319         IsEqualGUID(riid, &IID_IDirect3DRMMeshBuilder))
320     {
321         IClassFactory_AddRef(iface);
322         *ppvObject = This;
323         return S_OK;
324     }
325
326     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
327     return E_NOINTERFACE;
328 }
329
330 static ULONG WINAPI IDirect3DRMMeshBuilderImpl_AddRef(IDirect3DRMMeshBuilder* iface)
331 {
332     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
333
334     TRACE("(%p)\n", This);
335
336     return InterlockedIncrement(&This->ref);
337 }
338
339 static ULONG WINAPI IDirect3DRMMeshBuilderImpl_Release(IDirect3DRMMeshBuilder* iface)
340 {
341     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
342     ULONG ref = InterlockedDecrement(&This->ref);
343
344     TRACE("(%p)\n", This);
345
346     if (!ref)
347     {
348         HeapFree(GetProcessHeap(), 0, This->pVertices);
349         HeapFree(GetProcessHeap(), 0, This->pNormals);
350         HeapFree(GetProcessHeap(), 0, This->pFaceData);
351         HeapFree(GetProcessHeap(), 0, This);
352     }
353
354     return ref;
355 }
356
357 /*** IDirect3DRMObject methods ***/
358 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_Clone(IDirect3DRMMeshBuilder* iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj)
359 {
360     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
361
362     FIXME("(%p)->(%p,%s,%p): stub\n", This, pUnkOuter, debugstr_guid(riid), ppvObj);
363
364     return E_NOTIMPL;
365 }
366
367 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_AddDestroyCallback(IDirect3DRMMeshBuilder* iface, D3DRMOBJECTCALLBACK cb, LPVOID argument)
368 {
369     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
370
371     FIXME("(%p)->(%p,%p): stub\n", This, cb, argument);
372
373     return E_NOTIMPL;
374 }
375
376 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_DeleteDestroyCallback(IDirect3DRMMeshBuilder* iface, D3DRMOBJECTCALLBACK cb, LPVOID argument)
377 {
378     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
379
380     FIXME("(%p)->(%p,%p): stub\n", This, cb, argument);
381
382     return E_NOTIMPL;
383 }
384
385 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetAppData(IDirect3DRMMeshBuilder* iface, DWORD data)
386 {
387     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
388
389     FIXME("(%p)->(%u): stub\n", This, data);
390
391     return E_NOTIMPL;
392 }
393
394 static DWORD WINAPI IDirect3DRMMeshBuilderImpl_GetAppData(IDirect3DRMMeshBuilder* iface)
395 {
396     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
397
398     FIXME("(%p)->(): stub\n", This);
399
400     return 0;
401 }
402
403 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetName(IDirect3DRMMeshBuilder* iface, LPCSTR pName)
404 {
405     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
406
407     FIXME("(%p)->(%s): stub\n", This, pName);
408
409     return E_NOTIMPL;
410 }
411
412 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_GetName(IDirect3DRMMeshBuilder* iface, LPDWORD lpdwSize, LPSTR lpName)
413 {
414     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
415
416     FIXME("(%p)->(%p,%p): stub\n", This, lpdwSize, lpName);
417
418     return E_NOTIMPL;
419 }
420
421 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_GetClassName(IDirect3DRMMeshBuilder* iface, LPDWORD lpdwSize, LPSTR lpName)
422 {
423     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
424
425     FIXME("(%p)->(%p,%p): stub\n", This, lpdwSize, lpName);
426
427     return E_NOTIMPL;
428 }
429
430 /*** IDirect3DRMMeshBuilder methods ***/
431 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_Load(IDirect3DRMMeshBuilder* iface, LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK cb, LPVOID pArg)
432 {
433     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
434     DXFILELOADOPTIONS load_options;
435     LPDIRECTXFILE pDXFile = NULL;
436     LPDIRECTXFILEENUMOBJECT pEnumObject = NULL;
437     LPDIRECTXFILEDATA pData = NULL;
438     LPDIRECTXFILEOBJECT pObject = NULL;
439     LPDIRECTXFILEDATA pData2 = NULL;
440     const GUID* pGuid;
441     DWORD size;
442     Header* pHeader;
443     LPBYTE ptr;
444     HRESULT hr;
445     HRESULT ret = D3DRMERR_BADOBJECT;
446
447     FIXME("(%p)->(%p,%p,%x,%p,%p): partial stub\n", This, filename, name, loadflags, cb, pArg);
448
449     /* First free allocated buffers of previous mesh data */
450     HeapFree(GetProcessHeap(), 0, This->pVertices);
451     This->pVertices = NULL;
452     HeapFree(GetProcessHeap(), 0, This->pNormals);
453     This->pNormals = NULL;
454     HeapFree(GetProcessHeap(), 0, This->pFaceData);
455     This->pFaceData = NULL;
456     HeapFree(GetProcessHeap(), 0, This->pCoords2d);
457     This->pCoords2d = NULL;
458
459     if (loadflags == D3DRMLOAD_FROMMEMORY)
460     {
461         load_options = DXFILELOAD_FROMMEMORY;
462     }
463     else
464     {
465         FIXME("Load options %d not supported yet\n", loadflags);
466         return E_NOTIMPL;
467     }
468
469     hr = DirectXFileCreate(&pDXFile);
470     if (hr != DXFILE_OK)
471         goto end;
472
473     hr = IDirectXFile_RegisterTemplates(pDXFile, templates, strlen(templates));
474     if (hr != DXFILE_OK)
475         goto end;
476
477     hr = IDirectXFile_CreateEnumObject(pDXFile, filename, load_options, &pEnumObject);
478     if (hr != DXFILE_OK)
479         goto end;
480
481     hr = IDirectXFileEnumObject_GetNextDataObject(pEnumObject, &pData);
482     if (hr != DXFILE_OK)
483         goto end;
484
485     hr = IDirectXFileData_GetType(pData, &pGuid);
486     if (hr != DXFILE_OK)
487         goto end;
488
489     TRACE("Found object type whose GUID = %s\n", debugstr_guid(pGuid));
490
491     if (!IsEqualGUID(pGuid, &TID_DXFILEHeader))
492     {
493         ret = D3DRMERR_BADFILE;
494         goto end;
495     }
496
497     hr = IDirectXFileData_GetData(pData, NULL, &size, (void**)&pHeader);
498     if ((hr != DXFILE_OK) || (size != sizeof(Header)))
499         goto end;
500
501     TRACE("Version is %d %d %d\n", pHeader->major, pHeader->minor, pHeader->flags);
502
503     /* Version must be 1.0.x */
504     if ((pHeader->major != 1) || (pHeader->minor != 0))
505     {
506         ret = D3DRMERR_BADFILE;
507         goto end;
508     }
509
510     IDirectXFileData_Release(pData);
511     pData = NULL;
512
513     hr = IDirectXFileEnumObject_GetNextDataObject(pEnumObject, &pData);
514     if (hr != DXFILE_OK)
515     {
516         ret = D3DRMERR_NOTFOUND;
517         goto end;
518     }
519
520     hr = IDirectXFileData_GetType(pData, &pGuid);
521     if (hr != DXFILE_OK)
522         goto end;
523
524     TRACE("Found object type whose GUID = %s\n", debugstr_guid(pGuid));
525
526     if (!IsEqualGUID(pGuid, &TID_D3DRMMesh))
527     {
528         ret = D3DRMERR_NOTFOUND;
529         goto end;
530     }
531
532     hr = IDirectXFileData_GetData(pData, NULL, &size, (void**)&ptr);
533     if (hr != DXFILE_OK)
534         goto end;
535
536     This->nb_vertices = *(DWORD*)ptr;
537     This->nb_faces = *(DWORD*)(ptr + sizeof(DWORD) + This->nb_vertices * sizeof(D3DVECTOR));
538     This->face_data_size = size - sizeof(DWORD) - This->nb_vertices * sizeof(D3DVECTOR) - sizeof(DWORD);
539
540     TRACE("Mesh: nb_vertices = %d, nb_faces = %d, face_data_size = %d\n", This->nb_vertices, This->nb_faces, This->face_data_size);
541
542     This->pVertices = HeapAlloc(GetProcessHeap(), 0, This->nb_vertices * sizeof(D3DVECTOR));
543     memcpy(This->pVertices, ptr + sizeof(DWORD), This->nb_vertices * sizeof(D3DVECTOR));
544
545     This->pFaceData = HeapAlloc(GetProcessHeap(), 0, This->face_data_size);
546     memcpy(This->pFaceData, ptr + sizeof(DWORD) + This->nb_vertices * sizeof(D3DVECTOR) + sizeof(DWORD), This->face_data_size);
547
548     while (1)
549     {
550         hr =  IDirectXFileData_GetNextObject(pData, &pObject);
551         if (hr == DXFILEERR_NOMOREOBJECTS)
552         {
553             FIXME("no more object\n");
554             break;
555         }
556         if (hr != DXFILE_OK)
557            goto end;
558
559             hr = IDirectXFileObject_QueryInterface(pObject, &IID_IDirectXFileData, (void**)&pData2);
560         IDirectXFileObject_Release(pObject);
561         if (hr != DXFILE_OK)
562             goto end;
563
564         hr = IDirectXFileData_GetType(pData2, &pGuid);
565         if (hr != DXFILE_OK)
566         {
567             IDirectXFileData_Release(pData2);
568             goto end;
569         }
570
571         FIXME("Found object type whose GUID = %s\n", debugstr_guid(pGuid));
572
573         if (!IsEqualGUID(pGuid, &TID_D3DRMMeshNormals))
574         {
575             DWORD tmp;
576
577             hr = IDirectXFileData_GetData(pData, NULL, &size, (void**)&ptr);
578             if (hr != DXFILE_OK)
579                 goto end;
580
581             This->nb_normals = *(DWORD*)ptr;
582             tmp = *(DWORD*)(ptr + sizeof(DWORD) + This->nb_normals * sizeof(D3DVECTOR));
583
584             FIXME("MeshNormals: nb_normals = %d, nb_faces_normals = %d\n", This->nb_normals, tmp);
585
586             This->pNormals = HeapAlloc(GetProcessHeap(), 0, This->nb_normals * sizeof(D3DVECTOR));
587             memcpy(This->pNormals, ptr + sizeof(DWORD), This->nb_normals * sizeof(D3DVECTOR));
588         }
589         else if(!IsEqualGUID(pGuid, &TID_D3DRMMeshTextureCoords))
590         {
591             hr = IDirectXFileData_GetData(pData, NULL, &size, (void**)&ptr);
592             if (hr != DXFILE_OK)
593                 goto end;
594
595             This->nb_coords2d = *(DWORD*)ptr;
596
597             FIXME("MeshTextureCoords: nb_coords2d = %d\n", This->nb_coords2d);
598
599             This->pCoords2d = HeapAlloc(GetProcessHeap(), 0, This->nb_coords2d * sizeof(Coords2d));
600             memcpy(This->pCoords2d, ptr + sizeof(DWORD), This->nb_coords2d * sizeof(Coords2d));
601
602         }
603         else if(!IsEqualGUID(pGuid, &TID_D3DRMMeshMaterialList))
604         {
605             FIXME("MeshMaterialList not supported yet, ignoring...\n");
606         }
607         else
608         {
609             FIXME("Unknown GUID %s, ignoring...\n", debugstr_guid(pGuid));
610         }
611
612         IDirectXFileData_Release(pData2);
613     }
614
615     ret = D3DRM_OK;
616
617 end:
618     if (pData)
619         IDirectXFileData_Release(pData);
620     if (pEnumObject)
621         IDirectXFileEnumObject_Release(pEnumObject);
622     if (pDXFile)
623         IDirectXFile_Release(pDXFile);
624
625     if (ret != D3DRM_OK)
626     {
627         /* Clean mesh data */
628         This->nb_vertices = 0;
629         This->nb_normals = 0;
630         This->nb_faces = 0;
631         This->face_data_size = 0;
632         This->nb_coords2d = 0;
633         HeapFree(GetProcessHeap(), 0, This->pVertices);
634         This->pVertices = NULL;
635         HeapFree(GetProcessHeap(), 0, This->pNormals);
636         This->pNormals = NULL;
637         HeapFree(GetProcessHeap(), 0, This->pFaceData);
638         This->pFaceData = NULL;
639         HeapFree(GetProcessHeap(), 0, This->pCoords2d);
640         This->pCoords2d = NULL;
641     }
642
643     return ret;
644 }
645
646 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_Save(IDirect3DRMMeshBuilder* iface, const char *filename, D3DRMXOFFORMAT format, D3DRMSAVEOPTIONS save)
647 {
648     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
649
650     FIXME("(%p)->(%s,%d,%d): stub\n", This, filename, format, save);
651
652     return E_NOTIMPL;
653 }
654
655 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_Scale(IDirect3DRMMeshBuilder* iface, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz)
656 {
657     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
658
659     FIXME("(%p)->(%f,%f,%f): stub\n", This, sx, sy, sz);
660
661     return E_NOTIMPL;
662 }
663
664 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_Translate(IDirect3DRMMeshBuilder* iface, D3DVALUE tx, D3DVALUE ty, D3DVALUE tz)
665 {
666     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
667
668     FIXME("(%p)->(%f,%f,%f): stub\n", This, tx, ty, tz);
669
670     return E_NOTIMPL;
671 }
672
673 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetColorSource(IDirect3DRMMeshBuilder* iface, D3DRMCOLORSOURCE color)
674 {
675     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
676
677     FIXME("(%p)->(%x): stub\n", This, color);
678
679     return E_NOTIMPL;
680 }
681
682 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_GetBox(IDirect3DRMMeshBuilder* iface, D3DRMBOX *pBox)
683 {
684     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
685
686     FIXME("(%p)->(%p): stub\n", This, pBox);
687
688     return E_NOTIMPL;
689 }
690
691 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_GenerateNormals(IDirect3DRMMeshBuilder* iface)
692 {
693     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
694
695     FIXME("(%p)->(): stub\n", This);
696
697     return E_NOTIMPL;
698 }
699
700 static D3DRMCOLORSOURCE WINAPI IDirect3DRMMeshBuilderImpl_GetColorSource(IDirect3DRMMeshBuilder* iface)
701 {
702     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
703
704     FIXME("(%p)->(): stub\n", This);
705
706     return E_NOTIMPL;
707 }
708
709 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_AddMesh(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMMESH pMesh)
710 {
711     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
712
713     FIXME("(%p)->(%p): stub\n", This, pMesh);
714
715     return E_NOTIMPL;
716 }
717
718 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_AddMeshBuilder(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMMESHBUILDER pMeshBuilder)
719 {
720     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
721
722     FIXME("(%p)->(%p): stub\n", This, pMeshBuilder);
723
724     return E_NOTIMPL;
725 }
726
727 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_AddFrame(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMFRAME pFrame)
728 {
729     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
730
731     FIXME("(%p)->(%p): stub\n", This, pFrame);
732
733     return E_NOTIMPL;
734 }
735
736 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_AddFace(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMFACE pFace)
737 {
738     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
739
740     FIXME("(%p)->(%p): stub\n", This, pFace);
741
742     return E_NOTIMPL;
743 }
744
745 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_AddFaces(IDirect3DRMMeshBuilder* iface, DWORD vcount, D3DVECTOR *vertices, DWORD ncount, D3DVECTOR *normals, DWORD *data, LPDIRECT3DRMFACEARRAY* pFaceArray)
746 {
747     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
748
749     FIXME("(%p)->(%d,%p,%d,%p,%p,%p): stub\n", This, vcount, vertices, ncount, normals, data, pFaceArray);
750
751     return E_NOTIMPL;
752 }
753
754 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_ReserveSpace(IDirect3DRMMeshBuilder* iface, DWORD vertex_Count, DWORD normal_count, DWORD face_count)
755 {
756     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
757
758     FIXME("(%p)->(%d,%d,%d): stub\n", This, vertex_Count, normal_count, face_count);
759
760     return E_NOTIMPL;
761 }
762
763 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetColorRGB(IDirect3DRMMeshBuilder* iface, D3DVALUE red, D3DVALUE green, D3DVALUE blue)
764 {
765     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
766
767     FIXME("(%p)->(%f,%f,%f): stub\n", This, red, green, blue);
768
769     return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetColor(IDirect3DRMMeshBuilder* iface, D3DCOLOR color)
773 {
774     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
775
776     FIXME("(%p)->(%x): stub\n", This, color);
777
778     return E_NOTIMPL;
779 }
780
781 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetTexture(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMTEXTURE pTexture)
782 {
783     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
784
785     FIXME("(%p)->(%p): stub\n", This, pTexture);
786
787     return E_NOTIMPL;
788 }
789
790 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetMaterial(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMMATERIAL pMaterial)
791 {
792     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
793
794     FIXME("(%p)->(%p): stub\n", This, pMaterial);
795
796     return E_NOTIMPL;
797 }
798
799 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetTextureTopology(IDirect3DRMMeshBuilder* iface, BOOL wrap_u, BOOL wrap_v)
800 {
801     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
802
803     FIXME("(%p)->(%d,%d): stub\n", This, wrap_u, wrap_v);
804
805     return E_NOTIMPL;
806 }
807
808 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetQuality(IDirect3DRMMeshBuilder* iface, D3DRMRENDERQUALITY quality)
809 {
810     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
811
812     FIXME("(%p)->(%d): stub\n", This, quality);
813
814     return E_NOTIMPL;
815 }
816
817 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetPerspective(IDirect3DRMMeshBuilder* iface, BOOL enable)
818 {
819     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
820
821     FIXME("(%p)->(%d): stub\n", This, enable);
822
823     return E_NOTIMPL;
824 }
825
826 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetVertex(IDirect3DRMMeshBuilder* iface, DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z)
827 {
828     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
829
830     FIXME("(%p)->(%f,%f,%f): stub\n", This, x, y, z);
831
832     return E_NOTIMPL;
833 }
834
835 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetNormal(IDirect3DRMMeshBuilder* iface, DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z)
836 {
837     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
838
839     FIXME("(%p)->(%f,%f,%f): stub\n", This, x, y, z);
840
841     return E_NOTIMPL;
842 }
843
844 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetTextureCoordinates(IDirect3DRMMeshBuilder* iface, DWORD index, D3DVALUE u, D3DVALUE v)
845 {
846     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
847
848     FIXME("(%p)->(%f,%f): stub\n", This, u, v);
849
850     return E_NOTIMPL;
851 }
852
853 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetVertexColor(IDirect3DRMMeshBuilder* iface, DWORD index, D3DCOLOR color)
854 {
855     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
856
857     FIXME("(%p)->(%d,%x): stub\n", This, index, color);
858
859     return E_NOTIMPL;
860 }
861
862 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_SetVertexColorRGB(IDirect3DRMMeshBuilder* iface, DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue)
863 {
864     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
865
866     FIXME("(%p)->(%d,%f,%f,%f): stub\n", This, index, red, green, blue);
867
868     return E_NOTIMPL;
869 }
870
871 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_GetFaces(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMFACEARRAY* pFaceArray)
872 {
873     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
874
875     FIXME("(%p)->(%p): stub\n", This, pFaceArray);
876
877     return E_NOTIMPL;
878 }
879
880 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_GetVertices(IDirect3DRMMeshBuilder* iface, DWORD *vcount, D3DVECTOR *vertices, DWORD *ncount, D3DVECTOR *normals, DWORD *face_data_size, DWORD *face_data)
881 {
882     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
883
884     TRACE("(%p)->(%p,%p,%p,%p,%p,%p)\n", This, vcount, vertices, ncount, normals, face_data_size, face_data);
885
886     if (vcount)
887         *vcount = This->nb_vertices;
888     if (vertices && This->nb_vertices)
889         memcpy(vertices, This->pVertices, This->nb_vertices * sizeof(D3DVECTOR));
890     if (ncount)
891         *ncount = This->nb_normals;
892     if (normals && This->nb_normals)
893         memcpy(normals, This->pNormals, This->nb_normals * sizeof(D3DVECTOR));
894     if (face_data_size)
895         *face_data_size = This->face_data_size;
896     if (face_data && This->face_data_size)
897         memcpy(face_data, This->pFaceData, This->face_data_size);
898
899     return D3DRM_OK;
900 }
901
902 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_GetTextureCoordinates(IDirect3DRMMeshBuilder* iface, DWORD index, D3DVALUE *u, D3DVALUE *v)
903 {
904     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
905
906     FIXME("(%p)->(%d,%p,%p): stub\n", This, index, u, v);
907
908     if (index >= This->nb_coords2d)
909         return D3DRMERR_NOTFOUND;
910
911     *u = This->pCoords2d[index].u;
912     *v = This->pCoords2d[index].v;
913
914     return D3DRM_OK;
915 }
916
917 static int WINAPI IDirect3DRMMeshBuilderImpl_AddVertex(IDirect3DRMMeshBuilder* iface, D3DVALUE x, D3DVALUE y, D3DVALUE z)
918 {
919     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
920
921     FIXME("(%p)->(%f,%f,%f): stub\n", This, x, y, z);
922
923     return 0;
924 }
925
926 static int WINAPI IDirect3DRMMeshBuilderImpl_AddNormal(IDirect3DRMMeshBuilder* iface, D3DVALUE x, D3DVALUE y, D3DVALUE z)
927 {
928     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
929
930     FIXME("(%p)->(%f,%f,%f): stub\n", This, x, y, z);
931
932     return 0;
933 }
934
935 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_CreateFace(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMFACE* ppFace)
936 {
937     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
938
939     FIXME("(%p)->(%p): stub\n", This, ppFace);
940
941     return E_NOTIMPL;
942 }
943
944 static D3DRMRENDERQUALITY WINAPI IDirect3DRMMeshBuilderImpl_GetQuality(IDirect3DRMMeshBuilder* iface)
945 {
946     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
947
948     FIXME("(%p)->(): stub\n", This);
949
950     return 0;
951 }
952
953 static BOOL WINAPI IDirect3DRMMeshBuilderImpl_GetPerspective(IDirect3DRMMeshBuilder* iface)
954 {
955     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
956
957     FIXME("(%p)->(): stub\n", This);
958
959     return FALSE;
960 }
961
962 static int WINAPI IDirect3DRMMeshBuilderImpl_GetFaceCount(IDirect3DRMMeshBuilder* iface)
963 {
964     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
965
966     TRACE("(%p)->()\n", This);
967
968     return This->nb_faces;
969 }
970
971 static int WINAPI IDirect3DRMMeshBuilderImpl_GetVertexCount(IDirect3DRMMeshBuilder* iface)
972 {
973     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
974
975     TRACE("(%p)->()\n", This);
976
977     return This->nb_vertices;
978 }
979
980 static D3DCOLOR WINAPI IDirect3DRMMeshBuilderImpl_GetVertexColor(IDirect3DRMMeshBuilder* iface, DWORD index)
981 {
982     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
983
984     FIXME("(%p)->(%d): stub\n", This, index);
985
986     return 0;
987 }
988
989 static HRESULT WINAPI IDirect3DRMMeshBuilderImpl_CreateMesh(IDirect3DRMMeshBuilder* iface, LPDIRECT3DRMMESH* ppMesh)
990 {
991     IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder(iface);
992
993     FIXME("(%p)->(%p): stub\n", This, ppMesh);
994
995     return E_NOTIMPL;
996 }
997
998 static const struct IDirect3DRMMeshBuilderVtbl Direct3DRMMeshBuilder_Vtbl =
999 {
1000     /*** IUnknown methods ***/
1001     IDirect3DRMMeshBuilderImpl_QueryInterface,
1002     IDirect3DRMMeshBuilderImpl_AddRef,
1003     IDirect3DRMMeshBuilderImpl_Release,
1004     /*** IDirect3DRMObject methods ***/
1005     IDirect3DRMMeshBuilderImpl_Clone,
1006     IDirect3DRMMeshBuilderImpl_AddDestroyCallback,
1007     IDirect3DRMMeshBuilderImpl_DeleteDestroyCallback,
1008     IDirect3DRMMeshBuilderImpl_SetAppData,
1009     IDirect3DRMMeshBuilderImpl_GetAppData,
1010     IDirect3DRMMeshBuilderImpl_SetName,
1011     IDirect3DRMMeshBuilderImpl_GetName,
1012     IDirect3DRMMeshBuilderImpl_GetClassName,
1013     /*** IDirect3DRMMeshBuilder methods ***/
1014     IDirect3DRMMeshBuilderImpl_Load,
1015     IDirect3DRMMeshBuilderImpl_Save,
1016     IDirect3DRMMeshBuilderImpl_Scale,
1017     IDirect3DRMMeshBuilderImpl_Translate,
1018     IDirect3DRMMeshBuilderImpl_SetColorSource,
1019     IDirect3DRMMeshBuilderImpl_GetBox,
1020     IDirect3DRMMeshBuilderImpl_GenerateNormals,
1021     IDirect3DRMMeshBuilderImpl_GetColorSource,
1022     IDirect3DRMMeshBuilderImpl_AddMesh,
1023     IDirect3DRMMeshBuilderImpl_AddMeshBuilder,
1024     IDirect3DRMMeshBuilderImpl_AddFrame,
1025     IDirect3DRMMeshBuilderImpl_AddFace,
1026     IDirect3DRMMeshBuilderImpl_AddFaces,
1027     IDirect3DRMMeshBuilderImpl_ReserveSpace,
1028     IDirect3DRMMeshBuilderImpl_SetColorRGB,
1029     IDirect3DRMMeshBuilderImpl_SetColor,
1030     IDirect3DRMMeshBuilderImpl_SetTexture,
1031     IDirect3DRMMeshBuilderImpl_SetMaterial,
1032     IDirect3DRMMeshBuilderImpl_SetTextureTopology,
1033     IDirect3DRMMeshBuilderImpl_SetQuality,
1034     IDirect3DRMMeshBuilderImpl_SetPerspective,
1035     IDirect3DRMMeshBuilderImpl_SetVertex,
1036     IDirect3DRMMeshBuilderImpl_SetNormal,
1037     IDirect3DRMMeshBuilderImpl_SetTextureCoordinates,
1038     IDirect3DRMMeshBuilderImpl_SetVertexColor,
1039     IDirect3DRMMeshBuilderImpl_SetVertexColorRGB,
1040     IDirect3DRMMeshBuilderImpl_GetFaces,
1041     IDirect3DRMMeshBuilderImpl_GetVertices,
1042     IDirect3DRMMeshBuilderImpl_GetTextureCoordinates,
1043     IDirect3DRMMeshBuilderImpl_AddVertex,
1044     IDirect3DRMMeshBuilderImpl_AddNormal,
1045     IDirect3DRMMeshBuilderImpl_CreateFace,
1046     IDirect3DRMMeshBuilderImpl_GetQuality,
1047     IDirect3DRMMeshBuilderImpl_GetPerspective,
1048     IDirect3DRMMeshBuilderImpl_GetFaceCount,
1049     IDirect3DRMMeshBuilderImpl_GetVertexCount,
1050     IDirect3DRMMeshBuilderImpl_GetVertexColor,
1051     IDirect3DRMMeshBuilderImpl_CreateMesh
1052 };