wsdapi: Fix use-after-free when checking for unique prefix (Valgrind).
[wine.git] / dlls / d3dx9_36 / tests / xfile.c
blob46b4ee26564ea321e68325036f9c229265e4214e
1 /*
2 * Copyright 2012 Christian Costa
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.
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.
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
19 #include <stdio.h>
21 #include "wine/test.h"
22 #include "d3dx9.h"
23 #include "d3dx9xof.h"
25 static const char templates_bad_file_type1[] =
26 "xOf 0302txt 0064\n";
28 static const char templates_bad_file_version[] =
29 "xof 0102txt 0064\n";
31 static const char templates_bad_file_type2[] =
32 "xof 0302foo 0064\n";
34 static const char templates_bad_file_float_size[] =
35 "xof 0302txt 0050\n";
37 static const char templates_parse_error[] =
38 "xof 0302txt 0064"
39 "foobar;\n";
41 static const char templates[] =
42 "xof 0302txt 0064"
43 "template Header"
44 "{"
45 "<3D82AB43-62DA-11CF-AB39-0020AF71E433>"
46 "WORD major;"
47 "WORD minor;"
48 "DWORD flags;"
49 "}\n";
51 static char objects[] =
52 "xof 0302txt 0064\n"
53 "Header Object\n"
54 "{\n"
55 "1; 2; 3;\n"
56 "}\n";
58 static char object_noname[] =
59 "xof 0302txt 0064\n"
60 "Header\n"
61 "{\n"
62 "1; 2; 3;\n"
63 "}\n";
65 static char template_using_index_color_lower[] =
66 "xof 0302txt 0064\n"
67 "template MeshVertexColors\n"
68 "{\n"
69 "<1630B821-7842-11cf-8F52-0040333594A3>\n"
70 "DWORD nVertexColors;\n"
71 "array indexColor vertexColors[nVertexColors];\n"
72 "}\n";
74 static char template_using_index_color_upper[] =
75 "xof 0302txt 0064\n"
76 "template MeshVertexColors\n"
77 "{\n"
78 "<1630B821-7842-11cf-8F52-0040333594A3>\n"
79 "DWORD nVertexColors;\n"
80 "array IndexColor vertexColors[nVertexColors];\n"
81 "}\n";
83 static void test_templates(void)
85 ID3DXFile *d3dxfile;
86 HRESULT ret;
88 ret = D3DXFileCreate(NULL);
89 ok(ret == E_POINTER, "D3DXCreateFile returned %#x, expected %#x\n", ret, E_POINTER);
91 ret = D3DXFileCreate(&d3dxfile);
92 ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret);
94 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_bad_file_type1, sizeof(templates_bad_file_type1) - 1);
95 ok(ret == D3DXFERR_BADFILETYPE, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_BADFILETYPE);
97 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_bad_file_version, sizeof(templates_bad_file_version) - 1);
98 ok(ret == D3DXFERR_BADFILEVERSION, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_BADFILEVERSION);
100 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_bad_file_type2, sizeof(templates_bad_file_type2) - 1);
101 ok(ret == D3DXFERR_BADFILETYPE, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_BADFILETYPE);
103 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_bad_file_float_size, sizeof(templates_bad_file_float_size) - 1);
104 ok(ret == D3DXFERR_BADFILEFLOATSIZE, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_BADFILEFLOATSIZE);
106 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_parse_error, sizeof(templates_parse_error) - 1);
107 ok(ret == D3DXFERR_PARSEERROR, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_PARSEERROR);
109 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates, sizeof(templates) - 1);
110 ok(ret == S_OK, "RegisterTemplates failed with %#x\n", ret);
112 d3dxfile->lpVtbl->Release(d3dxfile);
115 static void test_lock_unlock(void)
117 ID3DXFile *d3dxfile;
118 D3DXF_FILELOADMEMORY memory;
119 ID3DXFileEnumObject *enum_object;
120 ID3DXFileData *data_object;
121 const void *data;
122 SIZE_T size;
123 HRESULT ret;
125 ret = D3DXFileCreate(&d3dxfile);
126 ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret);
128 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates, sizeof(templates) - 1);
129 ok(ret == S_OK, "RegisterTemplates failed with %#x\n", ret);
131 memory.lpMemory = objects;
132 memory.dSize = sizeof(objects) - 1;
134 ret = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &memory, D3DXF_FILELOAD_FROMMEMORY, &enum_object);
135 ok(ret == S_OK, "CreateEnumObject failed with %#x\n", ret);
137 ret = enum_object->lpVtbl->GetChild(enum_object, 0, &data_object);
138 ok(ret == S_OK, "GetChild failed with %#x\n", ret);
140 ret = data_object->lpVtbl->Unlock(data_object);
141 ok(ret == S_OK, "Unlock failed with %#x\n", ret);
142 ret = data_object->lpVtbl->Lock(data_object, &size, &data);
143 ok(ret == S_OK, "Lock failed with %#x\n", ret);
144 ret = data_object->lpVtbl->Lock(data_object, &size, &data);
145 ok(ret == S_OK, "Lock failed with %#x\n", ret);
146 ret = data_object->lpVtbl->Unlock(data_object);
147 ok(ret == S_OK, "Unlock failed with %#x\n", ret);
148 ret = data_object->lpVtbl->Unlock(data_object);
149 ok(ret == S_OK, "Unlock failed with %#x\n", ret);
151 data_object->lpVtbl->Release(data_object);
152 enum_object->lpVtbl->Release(enum_object);
153 d3dxfile->lpVtbl->Release(d3dxfile);
156 static void test_getname(void)
158 ID3DXFile *d3dxfile;
159 D3DXF_FILELOADMEMORY memory;
160 ID3DXFileEnumObject *enum_object;
161 ID3DXFileData *data_object;
162 SIZE_T length;
163 char name[100];
164 HRESULT ret;
166 ret = D3DXFileCreate(&d3dxfile);
167 ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret);
169 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates, sizeof(templates) - 1);
170 ok(ret == S_OK, "RegisterTemplates failed with %#x\n", ret);
172 /* Check object with name */
173 memory.lpMemory = objects;
174 memory.dSize = sizeof(objects) - 1;
175 ret = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &memory, D3DXF_FILELOAD_FROMMEMORY, &enum_object);
176 ok(ret == S_OK, "CreateEnumObject failed with %#x\n", ret);
177 ret = enum_object->lpVtbl->GetChild(enum_object, 0, &data_object);
178 ok(ret == S_OK, "GetChild failed with %#x\n", ret);
180 ret = data_object->lpVtbl->GetName(data_object, NULL, NULL);
181 ok(ret == D3DXFERR_BADVALUE, "GetName returned %#x, expected %#x\n", ret, D3DXFERR_BADVALUE);
182 ret = data_object->lpVtbl->GetName(data_object, name, NULL);
183 ok(ret == D3DXFERR_BADVALUE, "GetName returned %#x, expected %#x\n", ret, D3DXFERR_BADVALUE);
184 ret = data_object->lpVtbl->GetName(data_object, NULL, &length);
185 ok(ret == S_OK, "GetName failed with %#x\n", ret);
186 ok(length == 7, "Returned length should be 7 instead of %ld\n", length);
187 length = sizeof(name);
188 ret = data_object->lpVtbl->GetName(data_object, name, &length);
189 ok(ret == S_OK, "GetName failed with %#x\n", ret);
190 ok(length == 7, "Returned length should be 7 instead of %ld\n", length);
191 ok(!strcmp(name, "Object"), "Returned string should be 'Object' instead of '%s'\n", name);
192 length = 3;
193 ret = data_object->lpVtbl->GetName(data_object, name, &length);
194 ok(ret== D3DXFERR_BADVALUE, "GetName returned %#x, expected %#x\n", ret, D3DXFERR_BADVALUE);
196 data_object->lpVtbl->Release(data_object);
197 enum_object->lpVtbl->Release(enum_object);
199 /* Check object without name */
200 memory.lpMemory = object_noname;
201 memory.dSize = sizeof(object_noname) - 1;
202 ret = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &memory, D3DXF_FILELOAD_FROMMEMORY, &enum_object);
203 ok(ret == S_OK, "CreateEnumObject failed with %#x\n", ret);
204 ret = enum_object->lpVtbl->GetChild(enum_object, 0, &data_object);
205 ok(ret == S_OK, "GetChild failed with %#x\n", ret);
207 /* Contrary to d3dxof, d3dx9_36 returns an empty string with a null byte when no name is available.
208 * If the input size is 0, it returns a length of 1 without touching the buffer */
209 ret = data_object->lpVtbl->GetName(data_object, NULL, &length);
210 ok(ret == S_OK, "GetName failed with %#x\n", ret);
211 ok(length == 1, "Returned length should be 1 instead of %ld\n", length);
212 length = 0;
213 name[0] = 0x7f;
214 ret = data_object->lpVtbl->GetName(data_object, name, &length);
215 ok(ret == S_OK, "GetName failed with %#x\n", ret);
216 ok(length == 1, "Returned length should be 1 instead of %ld\n", length);
217 ok(name[0] == 0x7f, "First character is %#x instead of 0x7f\n", name[0]);
218 length = sizeof(name);
219 name[0] = 0x7f;
220 ret = data_object->lpVtbl->GetName(data_object, name, &length);
221 ok(ret == S_OK, "GetName failed with %#x\n", ret);
222 ok(length == 1, "Returned length should be 1 instead of %ld\n", length);
223 ok(name[0] == 0, "First character is %#x instead of 0x00\n", name[0]);
225 data_object->lpVtbl->Release(data_object);
226 enum_object->lpVtbl->Release(enum_object);
227 d3dxfile->lpVtbl->Release(d3dxfile);
230 static void test_type_index_color(void)
232 ID3DXFile *d3dxfile;
233 HRESULT ret;
235 ret = D3DXFileCreate(&d3dxfile);
236 ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret);
238 /* Test that 'indexColor' can be used (same as IndexedColor in standard templates) and is case sensitive */
239 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, template_using_index_color_lower, sizeof(template_using_index_color_lower) - 1);
240 ok(ret == S_OK, "RegisterTemplates failed with %#x\n", ret);
241 ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, template_using_index_color_upper, sizeof(template_using_index_color_upper) - 1);
242 ok(ret == D3DXFERR_PARSEERROR, "RegisterTemplates returned %#x instead of %#x\n", ret, D3DXFERR_PARSEERROR);
244 d3dxfile->lpVtbl->Release(d3dxfile);
247 static void process_data(ID3DXFileData *xfile_data, int level)
249 HRESULT ret;
250 char name[100];
251 GUID clsid;
252 GUID clsid_type;
253 SIZE_T len = sizeof(name);
254 int i;
255 const BYTE *data;
256 SIZE_T size;
257 SIZE_T children;
259 ret = xfile_data->lpVtbl->GetId(xfile_data, &clsid);
260 ok(ret == S_OK, "ID3DXFileData_GetId failed with %#x\n", ret);
261 ret = xfile_data->lpVtbl->GetName(xfile_data, name, &len);
262 ok(ret == S_OK, "ID3DXFileData_GetName failed with %#x\n", ret);
263 ret = xfile_data->lpVtbl->GetType(xfile_data, &clsid_type);
264 ok(ret == S_OK, "IDirectXFileData_GetType failed with %#x\n", ret);
265 ret = xfile_data->lpVtbl->Lock(xfile_data, &size, (const void**)&data);
266 ok(ret == S_OK, "IDirectXFileData_Lock failed with %#x\n", ret);
268 for (i = 0; i < level; i++)
269 printf(" ");
271 printf("Found object '%s' - %s - %s - %lu\n",
272 len ? name : "", wine_dbgstr_guid(&clsid), wine_dbgstr_guid(&clsid_type), size);
274 if (size)
276 int j;
277 for (j = 0; j < size; j++)
279 if (j && !(j%16))
280 printf("\n");
281 printf("%02x ", data[j]);
283 printf("\n");
286 ret = xfile_data->lpVtbl->Unlock(xfile_data);
287 ok(ret == S_OK, "ID3DXFileData_Unlock failed with %#x\n", ret);
289 ret = xfile_data->lpVtbl->GetChildren(xfile_data, &children);
290 ok(ret == S_OK, "ID3DXFileData_GetChildren failed with %#x\n", ret);
292 level++;
294 for (i = 0; i < children; i++)
296 ID3DXFileData *child;
297 int j;
299 ret = xfile_data->lpVtbl->GetChild(xfile_data, i, &child);
300 ok(ret == S_OK, "ID3DXFileData_GetChild failed with %#x\n", ret);
301 for (j = 0; j < level; j++)
302 printf(" ");
303 if (child->lpVtbl->IsReference(child))
304 printf("Found Data Reference (%d)\n", i + 1);
305 else
306 printf("Found Data (%d)\n", i + 1);
308 process_data(child, level);
310 child->lpVtbl->Release(child);
314 /* Dump an X file 'objects.x' and its related templates file 'templates.x' if they are both presents
315 * Useful for debug by comparing outputs from native and builtin dlls */
316 static void test_dump(void)
318 HRESULT ret;
319 ULONG ref;
320 ID3DXFile *xfile = NULL;
321 ID3DXFileEnumObject *xfile_enum_object = NULL;
322 HANDLE file;
323 void *data;
324 DWORD size;
325 SIZE_T children;
326 int i;
328 /* Dump data only if there is an object and a template */
329 file = CreateFileA("objects.x", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
330 if (file == INVALID_HANDLE_VALUE)
331 return;
332 CloseHandle(file);
334 file = CreateFileA("templates.x", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
335 if (file == INVALID_HANDLE_VALUE)
336 return;
338 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 10000);
340 if (!ReadFile(file, data, 10000, &size, NULL))
342 skip("Templates file is too big\n");
343 goto exit;
346 printf("Load templates file (%u bytes)\n", size);
348 ret = D3DXFileCreate(&xfile);
349 ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret);
351 ret = xfile->lpVtbl->RegisterTemplates(xfile, data, size);
352 ok(ret == S_OK, "ID3DXFileImpl_RegisterTemplates failed with %#x\n", ret);
354 ret = xfile->lpVtbl->CreateEnumObject(xfile, (void*)"objects.x", D3DXF_FILELOAD_FROMFILE, &xfile_enum_object);
355 ok(ret == S_OK, "ID3DXFile_CreateEnumObject failed with %#x\n", ret);
357 ret = xfile_enum_object->lpVtbl->GetChildren(xfile_enum_object, &children);
358 ok(ret == S_OK, "ID3DXFileEnumObject_GetChildren failed with %#x\n", ret);
360 for (i = 0; i < children; i++)
362 ID3DXFileData *child;
363 ret = xfile_enum_object->lpVtbl->GetChild(xfile_enum_object, i, &child);
364 ok(ret == S_OK, "ID3DXFileEnumObject_GetChild failed with %#x\n", ret);
365 printf("\n");
366 process_data(child, 0);
367 child->lpVtbl->Release(child);
370 ref = xfile_enum_object->lpVtbl->Release(xfile_enum_object);
371 ok(ref == 0, "Got refcount %u, expected 0\n", ref);
373 ref = xfile->lpVtbl->Release(xfile);
374 ok(ref == 0, "Got refcount %u, expected 0\n", ref);
377 exit:
378 CloseHandle(file);
379 HeapFree(GetProcessHeap(), 0, data);
382 START_TEST(xfile)
384 test_templates();
385 test_lock_unlock();
386 test_getname();
387 test_type_index_color();
388 test_dump();