2 * Some unit tests for d3dxof
4 * Copyright (C) 2008 Christian Costa
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.
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.
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
24 #include "wine/test.h"
28 static inline void debugstr_guid( char* buf, CONST GUID *id )
30 sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
31 id->Data1, id->Data2, id->Data3,
32 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
33 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
36 static HMODULE hd3dxof;
37 static HRESULT (WINAPI *pDirectXFileCreate)(LPDIRECTXFILE*);
43 "<3D82AB43-62DA-11CF-AB39-0020AF71E433>\n"
56 char empty_txt_file[] = "xof 0302txt 0064";
57 char empty_bin_file[] = "xof 0302bin 0064";
58 /* MSZip data is generated with the command "MAKECAB.EXE /D Compress=ON /D CompressionType=MSZip file packed"
59 * Data in cab is after the filename (null terminated) and the 32-bit checksum:
60 * size (16-bit), packed_size (16-bit) and compressed data (with leading 16-bit CK signature)
61 * Data in x files is preceding by 2 16-bit words: size with xof header (16 bytes) and a 0 value
62 * It does not seem possible to generate a MSZip data with no byte, so put just 1 byte here */
63 /* "\n" packed with MSZip => not text */
64 char empty_tzip_file[] = "xof 0302tzip0064\x11\x00\x00\x00\x01\x00\x05\x00\x43\x4b\xe3\x02\x00";
65 /* "\n" packed with MSZip => not token (token are 16-bit and there is only 1 byte) */
66 char empty_bzip_file[] = "xof 0302bzip0064\x11\x00\x00\x00\x01\x00\x05\x00\x43\x4b\xe3\x02\x00";
67 char empty_cmp_file[] = "xof 0302cmp 0064";
68 char empty_xxxx_file[] = "xof 0302xxxx0064";
70 static void init_function_pointers(void)
72 /* We have to use LoadLibrary as no d3dxof functions are referenced directly */
73 hd3dxof = LoadLibraryA("d3dxof.dll");
75 pDirectXFileCreate = (void *)GetProcAddress(hd3dxof, "DirectXFileCreate");
78 static ULONG getRefcount(IUnknown *iface)
80 IUnknown_AddRef(iface);
81 return IUnknown_Release(iface);
84 static void test_refcount(void)
88 LPDIRECTXFILE lpDirectXFile = NULL;
89 LPDIRECTXFILEENUMOBJECT lpdxfeo;
90 LPDIRECTXFILEDATA lpdxfd;
91 DXFILELOADMEMORY dxflm;
93 if (!pDirectXFileCreate)
95 win_skip("DirectXFileCreate is not available\n");
99 hr = pDirectXFileCreate(&lpDirectXFile);
100 ok(hr == DXFILE_OK, "DirectXFileCreate: %x\n", hr);
103 skip("Couldn't create DirectXFile interface\n");
107 ref = getRefcount( (IUnknown *) lpDirectXFile);
108 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
109 ref = IDirectXFile_AddRef(lpDirectXFile);
110 ok(ref == 2, "Got refcount %d, expected 1\n", ref);
111 ref = IDirectXFile_Release(lpDirectXFile);
112 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
114 hr = IDirectXFile_RegisterTemplates(lpDirectXFile, template, sizeof(template) - 1);
115 ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
117 dxflm.lpMemory = &object;
118 dxflm.dSize = sizeof(object) - 1;
119 hr = IDirectXFile_CreateEnumObject(lpDirectXFile, &dxflm, DXFILELOAD_FROMMEMORY, &lpdxfeo);
120 ok(hr == DXFILE_OK, "IDirectXFile_CreateEnumObject: %x\n", hr);
121 ref = getRefcount( (IUnknown *) lpDirectXFile);
122 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
123 ref = getRefcount( (IUnknown *) lpdxfeo);
124 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
126 hr = IDirectXFileEnumObject_GetNextDataObject(lpdxfeo, &lpdxfd);
127 ok(hr == DXFILE_OK, "IDirectXFileEnumObject_GetNextDataObject: %x\n", hr);
128 ref = getRefcount( (IUnknown *) lpDirectXFile);
129 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
130 ref = getRefcount( (IUnknown *) lpdxfeo);
131 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
132 /* Enum object gets references to all top level objects */
133 ref = getRefcount( (IUnknown *) lpdxfd);
134 ok(ref == 2, "Got refcount %d, expected 2\n", ref);
136 ref = IDirectXFile_Release(lpDirectXFile);
137 ok(ref == 0, "Got refcount %d, expected 0\n", ref);
138 /* Nothing changes for all other objects */
139 ref = getRefcount( (IUnknown *) lpdxfeo);
140 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
141 ref = getRefcount( (IUnknown *) lpdxfd);
142 ok(ref == 2, "Got refcount %d, expected 1\n", ref);
144 ref = IDirectXFileEnumObject_Release(lpdxfeo);
145 ok(ref == 0, "Got refcount %d, expected 0\n", ref);
146 /* Enum object releases references to all top level objects */
147 ref = getRefcount( (IUnknown *) lpdxfd);
148 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
150 ref = IDirectXFileData_Release(lpdxfd);
151 ok(ref == 0, "Got refcount %d, expected 0\n", ref);
154 static void test_CreateEnumObject(void)
158 LPDIRECTXFILE lpDirectXFile = NULL;
159 LPDIRECTXFILEENUMOBJECT lpdxfeo;
160 LPDIRECTXFILEDATA lpdxfd;
161 DXFILELOADMEMORY dxflm;
165 if (!pDirectXFileCreate)
167 win_skip("DirectXFileCreate is not available\n");
171 hr = pDirectXFileCreate(&lpDirectXFile);
172 ok(hr == DXFILE_OK, "DirectXFileCreate: %x\n", hr);
175 skip("Couldn't create DirectXFile interface\n");
179 hr = IDirectXFile_RegisterTemplates(lpDirectXFile, template, sizeof(template) - 1);
180 ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
182 dxflm.lpMemory = &object;
183 dxflm.dSize = sizeof(object) - 1;
184 /* Check that only lowest 4 bits are relevant in DXFILELOADOPTIONS */
185 hr = IDirectXFile_CreateEnumObject(lpDirectXFile, &dxflm, 0xFFFFFFF0 + DXFILELOAD_FROMMEMORY, &lpdxfeo);
186 ok(hr == DXFILE_OK, "IDirectXFile_CreateEnumObject: %x\n", hr);
188 hr = IDirectXFileEnumObject_GetNextDataObject(lpdxfeo, &lpdxfd);
189 ok(hr == DXFILE_OK, "IDirectXFileEnumObject_GetNextDataObject: %x\n", hr);
191 hr = IDirectXFileData_GetData(lpdxfd, NULL, &size, (void**)&pdata);
192 ok(hr == DXFILE_OK, "IDirectXFileData_GetData: %x\n", hr);
194 ok(size == 8, "Retrieved data size is wrong\n");
195 ok((*((WORD*)pdata) == 1) && (*((WORD*)(pdata+2)) == 2) && (*((DWORD*)(pdata+4)) == 3), "Retrieved data is wrong\n");
197 ref = IDirectXFileEnumObject_Release(lpdxfeo);
198 ok(ref == 0, "Got refcount %d, expected 0\n", ref);
200 ref = IDirectXFile_Release(lpDirectXFile);
201 ok(ref == 0, "Got refcount %d, expected 0\n", ref);
203 ref = IDirectXFileData_Release(lpdxfd);
204 ok(ref == 0, "Got refcount %d, expected 0\n", ref);
207 static void test_file_types(void)
210 LPDIRECTXFILE dxfile = NULL;
211 LPDIRECTXFILEENUMOBJECT enum_object;
212 DXFILELOADMEMORY lminfo;
214 if (!pDirectXFileCreate)
216 win_skip("DirectXFileCreate is not available\n");
220 hr = pDirectXFileCreate(&dxfile);
221 ok(hr == DXFILE_OK, "DirectXFileCreate: %x\n", hr);
224 skip("Couldn't create DirectXFile interface\n");
228 hr = IDirectXFile_RegisterTemplates(dxfile, empty_txt_file, sizeof(empty_txt_file) - 1);
229 ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
231 hr = IDirectXFile_RegisterTemplates(dxfile, empty_bin_file, sizeof(empty_bin_file) - 1);
232 ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
234 hr = IDirectXFile_RegisterTemplates(dxfile, empty_tzip_file, sizeof(empty_tzip_file) - 1);
235 todo_wine ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
237 hr = IDirectXFile_RegisterTemplates(dxfile, empty_bzip_file, sizeof(empty_bzip_file) - 1);
238 todo_wine ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
240 hr = IDirectXFile_RegisterTemplates(dxfile, empty_cmp_file, sizeof(empty_cmp_file) - 1);
241 ok(hr == DXFILEERR_BADFILETYPE, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
243 hr = IDirectXFile_RegisterTemplates(dxfile, empty_xxxx_file, sizeof(empty_xxxx_file) - 1);
244 ok(hr == DXFILEERR_BADFILETYPE, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
246 lminfo.lpMemory = empty_txt_file;
247 lminfo.dSize = sizeof(empty_txt_file) - 1;
248 hr = IDirectXFile_CreateEnumObject(dxfile, &lminfo, DXFILELOAD_FROMMEMORY, &enum_object);
249 ok(hr == DXFILE_OK, "IDirectXFile_CreateEnumObject: %x\n", hr);
250 if (hr == DXFILE_OK) IDirectXFileEnumObject_Release(enum_object);
252 lminfo.lpMemory = empty_bin_file;
253 lminfo.dSize = sizeof(empty_bin_file) - 1;
254 hr = IDirectXFile_CreateEnumObject(dxfile, &lminfo, DXFILELOAD_FROMMEMORY, &enum_object);
255 ok(hr == DXFILE_OK, "IDirectXFile_CreateEnumObject: %x\n", hr);
256 if (hr == DXFILE_OK) IDirectXFileEnumObject_Release(enum_object);
258 lminfo.lpMemory = empty_tzip_file;
259 lminfo.dSize = sizeof(empty_tzip_file) - 1;
260 hr = IDirectXFile_CreateEnumObject(dxfile, &lminfo, DXFILELOAD_FROMMEMORY, &enum_object);
261 todo_wine ok(hr == DXFILE_OK, "IDirectXFile_CreateEnumObject: %x\n", hr);
262 if (hr == DXFILE_OK) IDirectXFileEnumObject_Release(enum_object);
264 lminfo.lpMemory = empty_bzip_file;
265 lminfo.dSize = sizeof(empty_bzip_file) - 1;
266 hr = IDirectXFile_CreateEnumObject(dxfile, &lminfo, DXFILELOAD_FROMMEMORY, &enum_object);
267 todo_wine ok(hr == DXFILE_OK, "IDirectXFile_CreateEnumObject: %x\n", hr);
268 if (hr == DXFILE_OK) IDirectXFileEnumObject_Release(enum_object);
270 lminfo.lpMemory = empty_cmp_file;
271 lminfo.dSize = sizeof(empty_cmp_file) - 1;
272 hr = IDirectXFile_CreateEnumObject(dxfile, &lminfo, DXFILELOAD_FROMMEMORY, &enum_object);
273 ok(hr == DXFILEERR_BADFILETYPE, "IDirectXFile_CreateEnumObject: %x\n", hr);
275 lminfo.lpMemory = empty_xxxx_file;
276 lminfo.dSize = sizeof(empty_xxxx_file) - 1;
277 hr = IDirectXFile_CreateEnumObject(dxfile, &lminfo, DXFILELOAD_FROMMEMORY, &enum_object);
278 ok(hr == DXFILEERR_BADFILETYPE, "IDirectXFile_CreateEnumObject: %x\n", hr);
280 IDirectXFile_Release(dxfile);
283 /* Set it to 1 to expand the string when dumping the object. This is useful when there is
284 * only one string in a sub-object (very common). Use with care, this may lead to a crash. */
285 #define EXPAND_STRING 0
287 static void process_data(LPDIRECTXFILEDATA lpDirectXFileData, int* plevel)
292 CONST GUID* clsid_type = NULL;
294 char str_clsid_type[40];
296 LPDIRECTXFILEOBJECT pChildObj;
302 hr = IDirectXFileData_GetId(lpDirectXFileData, &clsid);
303 ok(hr == DXFILE_OK, "IDirectXFileData_GetId: %x\n", hr);
304 hr = IDirectXFileData_GetName(lpDirectXFileData, name, &len);
305 ok(hr == DXFILE_OK, "IDirectXFileData_GetName: %x\n", hr);
306 hr = IDirectXFileData_GetType(lpDirectXFileData, &clsid_type);
307 ok(hr == DXFILE_OK, "IDirectXFileData_GetType: %x\n", hr);
308 hr = IDirectXFileData_GetData(lpDirectXFileData, NULL, &size, (void**)&pData);
309 ok(hr == DXFILE_OK, "IDirectXFileData_GetData: %x\n", hr);
310 for (i = 0; i < *plevel; i++)
312 debugstr_guid(str_clsid, &clsid);
313 debugstr_guid(str_clsid_type, clsid_type);
314 printf("Found object '%s' - %s - %s - %d\n", name, str_clsid, str_clsid_type, size);
316 if (EXPAND_STRING && size == 4)
318 char * str = *(char**)pData;
319 printf("string %s\n", str);
323 for (k = 0; k < size; k++)
327 printf("%02x ", pData[k]);
332 while (SUCCEEDED(hr = IDirectXFileData_GetNextObject(lpDirectXFileData, &pChildObj)))
334 LPDIRECTXFILEDATA p1;
335 LPDIRECTXFILEDATAREFERENCE p2;
336 LPDIRECTXFILEBINARY p3;
339 hr = IDirectXFileObject_QueryInterface(pChildObj, &IID_IDirectXFileData, (void **) &p1);
342 for (i = 0; i < *plevel; i++)
344 printf("Found Data (%d)\n", j);
345 process_data(p1, plevel);
346 IDirectXFileData_Release(p1);
348 hr = IDirectXFileObject_QueryInterface(pChildObj, &IID_IDirectXFileDataReference, (void **) &p2);
351 LPDIRECTXFILEDATA pfdo;
352 for (i = 0; i < *plevel; i++)
354 printf("Found Data Reference (%d)\n", j);
356 hr = IDirectXFileDataReference_GetId(lpDirectXFileData, &clsid);
357 ok(hr == DXFILE_OK, "IDirectXFileData_GetId: %x\n", hr);
358 hr = IDirectXFileDataReference_GetName(lpDirectXFileData, name, &len);
359 ok(hr == DXFILE_OK, "IDirectXFileData_GetName: %x\n", hr);
361 IDirectXFileDataReference_Resolve(p2, &pfdo);
362 process_data(pfdo, plevel);
363 IDirectXFileData_Release(pfdo);
364 IDirectXFileDataReference_Release(p2);
366 hr = IDirectXFileObject_QueryInterface(pChildObj, &IID_IDirectXFileBinary, (void **) &p3);
369 for (i = 0; i < *plevel; i++)
371 printf("Found Binary (%d)\n", j);
372 IDirectXFileBinary_Release(p3);
376 ok(hr == DXFILE_OK || hr == DXFILEERR_NOMOREOBJECTS, "IDirectXFileData_GetNextObject: %x\n", hr);
379 static void test_dump(void)
383 LPDIRECTXFILE lpDirectXFile = NULL;
384 LPDIRECTXFILEENUMOBJECT lpDirectXFileEnumObject = NULL;
385 LPDIRECTXFILEDATA lpDirectXFileData = NULL;
387 LPVOID pvData = NULL;
390 if (!pDirectXFileCreate)
392 win_skip("DirectXFileCreate is not available\n");
396 /* Dump data only if there is an object and a template */
397 hFile = CreateFileA("objects.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
398 if (hFile == INVALID_HANDLE_VALUE)
402 hFile = CreateFileA("templates.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
403 if (hFile == INVALID_HANDLE_VALUE)
406 pvData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 10000);
408 if (!ReadFile(hFile, pvData, 10000, &cbSize, NULL))
410 skip("Template file is too big\n");
414 printf("Load %d bytes\n", cbSize);
416 hr = pDirectXFileCreate(&lpDirectXFile);
417 ok(hr == DXFILE_OK, "DirectXFileCreate: %x\n", hr);
420 skip("Couldn't create DirectXFile interface\n");
424 hr = IDirectXFile_RegisterTemplates(lpDirectXFile, pvData, cbSize);
425 ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
427 hr = IDirectXFile_CreateEnumObject(lpDirectXFile, (LPVOID)"objects.txt", DXFILELOAD_FROMFILE, &lpDirectXFileEnumObject);
428 ok(hr == DXFILE_OK, "IDirectXFile_CreateEnumObject: %x\n", hr);
430 while (SUCCEEDED(hr = IDirectXFileEnumObject_GetNextDataObject(lpDirectXFileEnumObject, &lpDirectXFileData)))
434 process_data(lpDirectXFileData, &level);
435 IDirectXFileData_Release(lpDirectXFileData);
437 ok(hr == DXFILE_OK || hr == DXFILEERR_NOMOREOBJECTS, "IDirectXFileEnumObject_GetNextDataObject: %x\n", hr);
439 ref = IDirectXFile_Release(lpDirectXFileEnumObject);
440 ok(ref == 0, "Got refcount %d, expected 0\n", ref);
442 ref = IDirectXFile_Release(lpDirectXFile);
443 ok(ref == 0, "Got refcount %d, expected 0\n", ref);
448 HeapFree(GetProcessHeap(), 0, pvData);
453 init_function_pointers();
456 test_CreateEnumObject();
460 FreeLibrary(hd3dxof);