hlink/tests: Add a trailing '\n' to an ok() call.
[wine] / dlls / d3dxof / tests / d3dxof.c
1 /*
2  * Some unit tests for d3dxof
3  *
4  * Copyright (C) 2008 Christian Costa
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 #define COBJMACROS
21
22 #include <assert.h>
23 #include <stdio.h>
24 #include "wine/test.h"
25 #include "initguid.h"
26 #include "dxfile.h"
27
28 static inline void debugstr_guid( char* buf, CONST GUID *id )
29 {
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] );
34 }
35
36 static HMODULE hd3dxof;
37 static HRESULT (WINAPI *pDirectXFileCreate)(LPDIRECTXFILE*);
38
39 char template[] =
40 "xof 0302txt 0064\n"
41 "template Header\n"
42 "{\n"
43 "<3D82AB43-62DA-11CF-AB39-0020AF71E433>\n"
44 "WORD major;\n"
45 "WORD minor;\n"
46 "DWORD flags;\n"
47 "}\n";
48
49 char object[] =
50 "xof 0302txt 0064\n"
51 "Header Object\n"
52 "{\n"
53 "1; 2; 3;\n"
54 "}\n";
55
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";
69
70 static void init_function_pointers(void)
71 {
72     /* We have to use LoadLibrary as no d3dxof functions are referenced directly */
73     hd3dxof = LoadLibraryA("d3dxof.dll");
74
75     pDirectXFileCreate = (void *)GetProcAddress(hd3dxof, "DirectXFileCreate");
76 }
77
78 static ULONG getRefcount(IUnknown *iface)
79 {
80     IUnknown_AddRef(iface);
81     return IUnknown_Release(iface);
82 }
83
84 static void test_refcount(void)
85 {
86     HRESULT hr;
87     ULONG ref;
88     LPDIRECTXFILE lpDirectXFile = NULL;
89     LPDIRECTXFILEENUMOBJECT lpdxfeo;
90     LPDIRECTXFILEDATA lpdxfd;
91     DXFILELOADMEMORY dxflm;
92
93     if (!pDirectXFileCreate)
94     {
95         win_skip("DirectXFileCreate is not available\n");
96         return;
97     }
98
99     hr = pDirectXFileCreate(&lpDirectXFile);
100     ok(hr == DXFILE_OK, "DirectXFileCreate: %x\n", hr);
101     if(!lpDirectXFile)
102     {
103         skip("Couldn't create DirectXFile interface\n");
104         return;
105     }
106
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);
113
114     hr = IDirectXFile_RegisterTemplates(lpDirectXFile, template, sizeof(template) - 1);
115     ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
116
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);
125
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);
135
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);
143
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);
149
150     ref = IDirectXFileData_Release(lpdxfd);
151     ok(ref == 0, "Got refcount %d, expected 0\n", ref);
152 }
153
154 static void test_CreateEnumObject(void)
155 {
156     HRESULT hr;
157     ULONG ref;
158     LPDIRECTXFILE lpDirectXFile = NULL;
159     LPDIRECTXFILEENUMOBJECT lpdxfeo;
160     LPDIRECTXFILEDATA lpdxfd;
161     DXFILELOADMEMORY dxflm;
162     BYTE* pdata;
163     DWORD size;
164
165     if (!pDirectXFileCreate)
166     {
167         win_skip("DirectXFileCreate is not available\n");
168         return;
169     }
170
171     hr = pDirectXFileCreate(&lpDirectXFile);
172     ok(hr == DXFILE_OK, "DirectXFileCreate: %x\n", hr);
173     if(!lpDirectXFile)
174     {
175         skip("Couldn't create DirectXFile interface\n");
176         return;
177     }
178
179     hr = IDirectXFile_RegisterTemplates(lpDirectXFile, template, sizeof(template) - 1);
180     ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
181
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);
187
188     hr = IDirectXFileEnumObject_GetNextDataObject(lpdxfeo, &lpdxfd);
189     ok(hr == DXFILE_OK, "IDirectXFileEnumObject_GetNextDataObject: %x\n", hr);
190
191     hr = IDirectXFileData_GetData(lpdxfd, NULL, &size, (void**)&pdata);
192     ok(hr == DXFILE_OK, "IDirectXFileData_GetData: %x\n", hr);
193
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");
196
197     ref = IDirectXFileEnumObject_Release(lpdxfeo);
198     ok(ref == 0, "Got refcount %d, expected 0\n", ref);
199
200     ref = IDirectXFile_Release(lpDirectXFile);
201     ok(ref == 0, "Got refcount %d, expected 0\n", ref);
202
203     ref = IDirectXFileData_Release(lpdxfd);
204     ok(ref == 0, "Got refcount %d, expected 0\n", ref);
205 }
206
207 static void test_file_types(void)
208 {
209     HRESULT hr;
210     LPDIRECTXFILE dxfile = NULL;
211     LPDIRECTXFILEENUMOBJECT enum_object;
212     DXFILELOADMEMORY lminfo;
213
214     if (!pDirectXFileCreate)
215     {
216         win_skip("DirectXFileCreate is not available\n");
217         return;
218     }
219
220     hr = pDirectXFileCreate(&dxfile);
221     ok(hr == DXFILE_OK, "DirectXFileCreate: %x\n", hr);
222     if (!dxfile)
223     {
224         skip("Couldn't create DirectXFile interface\n");
225         return;
226     }
227
228     hr = IDirectXFile_RegisterTemplates(dxfile, empty_txt_file, sizeof(empty_txt_file) - 1);
229     ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
230
231     hr = IDirectXFile_RegisterTemplates(dxfile, empty_bin_file, sizeof(empty_bin_file) - 1);
232     ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
233
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);
236
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);
239
240     hr = IDirectXFile_RegisterTemplates(dxfile, empty_cmp_file, sizeof(empty_cmp_file) - 1);
241     ok(hr == DXFILEERR_BADFILETYPE, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
242
243     hr = IDirectXFile_RegisterTemplates(dxfile, empty_xxxx_file, sizeof(empty_xxxx_file) - 1);
244     ok(hr == DXFILEERR_BADFILETYPE, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
245
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);
251
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);
257
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);
263
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);
269
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);
274
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);
279
280     IDirectXFile_Release(dxfile);
281 }
282
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
286
287 static void process_data(LPDIRECTXFILEDATA lpDirectXFileData, int* plevel)
288 {
289     HRESULT hr;
290     char name[100];
291     GUID clsid;
292     CONST GUID* clsid_type = NULL;
293     char str_clsid[40];
294     char str_clsid_type[40];
295     DWORD len= 100;
296     LPDIRECTXFILEOBJECT pChildObj;
297     int i;
298     int j = 0;
299     LPBYTE pData;
300     DWORD k, size;
301
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++)
311         printf("  ");
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);
315
316     if (EXPAND_STRING && size == 4)
317     {
318         char * str = *(char**)pData;
319         printf("string %s\n", str);
320     }
321     else if (size)
322     {
323         for (k = 0; k < size; k++)
324         {
325             if (k && !(k%16))
326                 printf("\n");
327             printf("%02x ", pData[k]);
328         }
329         printf("\n");
330     }
331     (*plevel)++;
332     while (SUCCEEDED(hr = IDirectXFileData_GetNextObject(lpDirectXFileData, &pChildObj)))
333     {
334         LPDIRECTXFILEDATA p1;
335         LPDIRECTXFILEDATAREFERENCE p2;
336         LPDIRECTXFILEBINARY p3;
337         j++;
338
339         hr = IDirectXFileObject_QueryInterface(pChildObj, &IID_IDirectXFileData, (void **) &p1);
340         if (SUCCEEDED(hr))
341         {
342             for (i = 0; i < *plevel; i++)
343                 printf("  ");
344             printf("Found Data (%d)\n", j);
345             process_data(p1, plevel);
346             IDirectXFileData_Release(p1);
347         }
348         hr = IDirectXFileObject_QueryInterface(pChildObj, &IID_IDirectXFileDataReference, (void **) &p2);
349         if (SUCCEEDED(hr))
350         {
351             LPDIRECTXFILEDATA pfdo;
352             for (i = 0; i < *plevel; i++)
353                 printf("  ");
354             printf("Found Data Reference (%d)\n", j);
355 #if 0
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);
360 #endif
361             IDirectXFileDataReference_Resolve(p2, &pfdo);
362             process_data(pfdo, plevel);
363             IDirectXFileData_Release(pfdo);
364             IDirectXFileDataReference_Release(p2);
365         }
366         hr = IDirectXFileObject_QueryInterface(pChildObj, &IID_IDirectXFileBinary, (void **) &p3);
367         if (SUCCEEDED(hr))
368         {
369             for (i = 0; i < *plevel; i++)
370                 printf("  ");
371             printf("Found Binary (%d)\n", j);
372             IDirectXFileBinary_Release(p3);
373         }
374     }
375     (*plevel)--;
376     ok(hr == DXFILE_OK || hr == DXFILEERR_NOMOREOBJECTS, "IDirectXFileData_GetNextObject: %x\n", hr);
377 }
378
379 static void test_dump(void)
380 {
381     HRESULT hr;
382     ULONG ref;
383     LPDIRECTXFILE lpDirectXFile = NULL;
384     LPDIRECTXFILEENUMOBJECT lpDirectXFileEnumObject = NULL;
385     LPDIRECTXFILEDATA lpDirectXFileData = NULL;
386     HANDLE hFile;
387     LPVOID pvData = NULL;
388     DWORD cbSize;
389
390     if (!pDirectXFileCreate)
391     {
392         win_skip("DirectXFileCreate is not available\n");
393         goto exit;
394     }
395
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)
399       return;
400     CloseHandle(hFile);
401
402     hFile = CreateFileA("templates.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
403     if (hFile == INVALID_HANDLE_VALUE)
404       return;
405
406     pvData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 10000);
407
408     if (!ReadFile(hFile, pvData, 10000, &cbSize, NULL))
409     {
410       skip("Template file is too big\n");
411       goto exit;
412     }
413
414     printf("Load %d bytes\n", cbSize);
415
416     hr = pDirectXFileCreate(&lpDirectXFile);
417     ok(hr == DXFILE_OK, "DirectXFileCreate: %x\n", hr);
418     if(!lpDirectXFile)
419     {
420         skip("Couldn't create DirectXFile interface\n");
421         goto exit;
422     }
423
424     hr = IDirectXFile_RegisterTemplates(lpDirectXFile, pvData, cbSize);
425     ok(hr == DXFILE_OK, "IDirectXFileImpl_RegisterTemplates: %x\n", hr);
426
427     hr = IDirectXFile_CreateEnumObject(lpDirectXFile, (LPVOID)"objects.txt", DXFILELOAD_FROMFILE, &lpDirectXFileEnumObject);
428     ok(hr == DXFILE_OK, "IDirectXFile_CreateEnumObject: %x\n", hr);
429
430     while (SUCCEEDED(hr = IDirectXFileEnumObject_GetNextDataObject(lpDirectXFileEnumObject, &lpDirectXFileData)))
431     {
432         int level = 0;
433         printf("\n");
434         process_data(lpDirectXFileData, &level);
435         IDirectXFileData_Release(lpDirectXFileData);
436     }
437     ok(hr == DXFILE_OK || hr == DXFILEERR_NOMOREOBJECTS, "IDirectXFileEnumObject_GetNextDataObject: %x\n", hr);
438
439     ref = IDirectXFile_Release(lpDirectXFileEnumObject);
440     ok(ref == 0, "Got refcount %d, expected 0\n", ref);
441
442     ref = IDirectXFile_Release(lpDirectXFile);
443     ok(ref == 0, "Got refcount %d, expected 0\n", ref);
444
445     CloseHandle(hFile);
446
447 exit:
448     HeapFree(GetProcessHeap(), 0, pvData);
449 }
450
451 START_TEST(d3dxof)
452 {
453     init_function_pointers();
454
455     test_refcount();
456     test_CreateEnumObject();
457     test_file_types();
458     test_dump();
459
460     FreeLibrary(hd3dxof);
461 }