hlink: Implement IHlinkBrowseContext::GetBrowseWindowInfo.
[wine] / dlls / dxdiagn / tests / container.c
1 /*
2  * Unit tests for IDxDiagContainer
3  *
4  * Copyright 2010 Andrew Nguyen
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 #define COBJMACROS
22
23 #include <stdio.h>
24 #include "dxdiag.h"
25 #include "wine/test.h"
26
27 static IDxDiagProvider *pddp;
28 static IDxDiagContainer *pddc;
29
30 static BOOL create_root_IDxDiagContainer(void)
31 {
32     HRESULT hr;
33     DXDIAG_INIT_PARAMS params;
34
35     hr = CoCreateInstance(&CLSID_DxDiagProvider, NULL, CLSCTX_INPROC_SERVER,
36                           &IID_IDxDiagProvider, (LPVOID*)&pddp);
37     if (SUCCEEDED(hr))
38     {
39         params.dwSize = sizeof(params);
40         params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
41         params.bAllowWHQLChecks = FALSE;
42         params.pReserved = NULL;
43         hr = IDxDiagProvider_Initialize(pddp, &params);
44         if (SUCCEEDED(hr))
45         {
46             hr = IDxDiagProvider_GetRootContainer(pddp, &pddc);
47             if (SUCCEEDED(hr))
48                 return TRUE;
49         }
50         IDxDiagProvider_Release(pddp);
51     }
52     return FALSE;
53 }
54
55 static void test_GetNumberOfChildContainers(void)
56 {
57     HRESULT hr;
58     DWORD count;
59
60     if (!create_root_IDxDiagContainer())
61     {
62         skip("Unable to create the root IDxDiagContainer\n");
63         return;
64     }
65
66     hr = IDxDiagContainer_GetNumberOfChildContainers(pddc, NULL);
67     ok(hr == E_INVALIDARG,
68        "Expected IDxDiagContainer::GetNumberOfChildContainers to return E_INVALIDARG, got 0x%08x\n", hr);
69
70     hr = IDxDiagContainer_GetNumberOfChildContainers(pddc, &count);
71     ok(hr == S_OK,
72        "Expected IDxDiagContainer::GetNumberOfChildContainers to return S_OK, got 0x%08x\n", hr);
73     if (hr == S_OK)
74         ok(count != 0, "Expected the number of child containers for the root container to be non-zero\n");
75
76     IDxDiagContainer_Release(pddc);
77     IDxDiagProvider_Release(pddp);
78 }
79
80 static void test_GetNumberOfProps(void)
81 {
82     HRESULT hr;
83     DWORD count;
84
85     if (!create_root_IDxDiagContainer())
86     {
87         skip("Unable to create the root IDxDiagContainer\n");
88         return;
89     }
90
91     hr = IDxDiagContainer_GetNumberOfProps(pddc, NULL);
92     ok(hr == E_INVALIDARG, "Expected IDxDiagContainer::GetNumberOfProps to return E_INVALIDARG, got 0x%08x\n", hr);
93
94     hr = IDxDiagContainer_GetNumberOfProps(pddc, &count);
95     ok(hr == S_OK, "Expected IDxDiagContainer::GetNumberOfProps to return S_OK, got 0x%08x\n", hr);
96     if (hr == S_OK)
97         ok(count == 0, "Expected the number of properties for the root container to be zero\n");
98
99     IDxDiagContainer_Release(pddc);
100     IDxDiagProvider_Release(pddp);
101 }
102
103 static void test_EnumChildContainerNames(void)
104 {
105     HRESULT hr;
106     WCHAR container[256];
107     DWORD maxcount, index;
108     static const WCHAR testW[] = {'t','e','s','t',0};
109     static const WCHAR zerotestW[] = {0,'e','s','t',0};
110
111     if (!create_root_IDxDiagContainer())
112     {
113         skip("Unable to create the root IDxDiagContainer\n");
114         return;
115     }
116
117     /* Test various combinations of invalid parameters. */
118     hr = IDxDiagContainer_EnumChildContainerNames(pddc, 0, NULL, 0);
119     ok(hr == E_INVALIDARG,
120        "Expected IDxDiagContainer::EnumChildContainerNames to return E_INVALIDARG, got 0x%08x\n", hr);
121
122     hr = IDxDiagContainer_EnumChildContainerNames(pddc, 0, NULL, sizeof(container)/sizeof(WCHAR));
123     ok(hr == E_INVALIDARG,
124        "Expected IDxDiagContainer::EnumChildContainerNames to return E_INVALIDARG, got 0x%08x\n", hr);
125
126     /* Test the conditions in which the output buffer can be modified. */
127     memcpy(container, testW, sizeof(testW));
128     hr = IDxDiagContainer_EnumChildContainerNames(pddc, 0, container, 0);
129     ok(hr == E_INVALIDARG,
130        "Expected IDxDiagContainer::EnumChildContainerNames to return E_INVALIDARG, got 0x%08x\n", hr);
131     ok(!memcmp(container, testW, sizeof(testW)),
132        "Expected the container buffer to be untouched, got %s\n", wine_dbgstr_w(container));
133
134     memcpy(container, testW, sizeof(testW));
135     hr = IDxDiagContainer_EnumChildContainerNames(pddc, ~0, container, 0);
136     ok(hr == E_INVALIDARG,
137        "Expected IDxDiagContainer::EnumChildContainerNames to return E_INVALIDARG, got 0x%08x\n", hr);
138     ok(!memcmp(container, testW, sizeof(testW)),
139        "Expected the container buffer to be untouched, got %s\n", wine_dbgstr_w(container));
140
141     memcpy(container, testW, sizeof(testW));
142     hr = IDxDiagContainer_EnumChildContainerNames(pddc, ~0, container, sizeof(container)/sizeof(WCHAR));
143     ok(hr == E_INVALIDARG,
144        "Expected IDxDiagContainer::EnumChildContainerNames to return E_INVALIDARG, got 0x%08x\n", hr);
145     ok(!memcmp(container, zerotestW, sizeof(zerotestW)),
146        "Expected the container buffer string to be empty, got %s\n", wine_dbgstr_w(container));
147
148     hr = IDxDiagContainer_GetNumberOfChildContainers(pddc, &maxcount);
149     ok(hr == S_OK, "Expected IDxDiagContainer::GetNumberOfChildContainers to return S_OK, got 0x%08x\n", hr);
150     if (FAILED(hr))
151     {
152         skip("IDxDiagContainer::GetNumberOfChildContainers failed\n");
153         goto cleanup;
154     }
155
156     trace("Starting child container enumeration of the root container:\n");
157
158     /* We should be able to enumerate as many child containers as the value
159      * that IDxDiagContainer::GetNumberOfChildContainers returns. */
160     for (index = 0; index <= maxcount; index++)
161     {
162         /* A buffer size of 1 is unlikely to be valid, as only a null terminator
163          * could be stored, and it is unlikely that a container name could be empty. */
164         DWORD buffersize = 1;
165         memcpy(container, testW, sizeof(testW));
166         hr = IDxDiagContainer_EnumChildContainerNames(pddc, index, container, buffersize);
167         if (hr == E_INVALIDARG)
168         {
169             /* We should get here when index is one more than the maximum index value. */
170             ok(maxcount == index,
171                "Expected IDxDiagContainer::EnumChildContainerNames to return E_INVALIDARG "
172                "on the last index %d, got 0x%08x\n", index, hr);
173             ok(container[0] == '\0',
174                "Expected the container buffer string to be empty, got %s\n", wine_dbgstr_w(container));
175             break;
176         }
177         else if (hr == DXDIAG_E_INSUFFICIENT_BUFFER)
178         {
179             WCHAR temp[256];
180
181             ok(container[0] == '\0',
182                "Expected the container buffer string to be empty, got %s\n", wine_dbgstr_w(container));
183
184             /* Get the container name to compare against. */
185             hr = IDxDiagContainer_EnumChildContainerNames(pddc, index, temp, sizeof(temp)/sizeof(WCHAR));
186             ok(hr == S_OK,
187                "Expected IDxDiagContainer::EnumChildContainerNames to return S_OK, got 0x%08x\n", hr);
188
189             /* Show that the DirectX SDK's stipulation that the buffer be at
190              * least 256 characters long is a mere suggestion, and smaller sizes
191              * can be acceptable also. IDxDiagContainer::EnumChildContainerNames
192              * doesn't provide a way of getting the exact size required, so the
193              * buffersize value will be iterated to at most 256 characters. */
194             for (buffersize = 2; buffersize <= 256; buffersize++)
195             {
196                 memcpy(container, testW, sizeof(testW));
197                 hr = IDxDiagContainer_EnumChildContainerNames(pddc, index, container, buffersize);
198                 if (hr != DXDIAG_E_INSUFFICIENT_BUFFER)
199                     break;
200
201                 ok(!memcmp(temp, container, sizeof(WCHAR)*(buffersize - 1)),
202                    "Expected truncated container name string, got %s\n", wine_dbgstr_w(container));
203             }
204
205             ok(hr == S_OK,
206                "Expected IDxDiagContainer::EnumChildContainerNames to return S_OK, "
207                "got hr = 0x%08x, buffersize = %d\n", hr, buffersize);
208             if (hr == S_OK)
209                 trace("pddc[%d] = %s, length = %d\n", index, wine_dbgstr_w(container), buffersize);
210         }
211         else
212         {
213             ok(0, "IDxDiagContainer::EnumChildContainerNames unexpectedly returned 0x%08x\n", hr);
214             break;
215         }
216     }
217
218 cleanup:
219     IDxDiagContainer_Release(pddc);
220     IDxDiagProvider_Release(pddp);
221 }
222
223 static void test_GetChildContainer(void)
224 {
225     HRESULT hr;
226     WCHAR container[256] = {0};
227     IDxDiagContainer *child;
228
229     if (!create_root_IDxDiagContainer())
230     {
231         skip("Unable to create the root IDxDiagContainer\n");
232         return;
233     }
234
235     /* Test various combinations of invalid parameters. */
236     hr = IDxDiagContainer_GetChildContainer(pddc, NULL, NULL);
237     ok(hr == E_INVALIDARG,
238        "Expected IDxDiagContainer::GetChildContainer to return E_INVALIDARG, got 0x%08x\n", hr);
239
240     child = (void*)0xdeadbeef;
241     hr = IDxDiagContainer_GetChildContainer(pddc, NULL, &child);
242     ok(hr == E_INVALIDARG,
243        "Expected IDxDiagContainer::GetChildContainer to return E_INVALIDARG, got 0x%08x\n", hr);
244     ok(child == (void*)0xdeadbeef, "Expected output pointer to be unchanged, got %p\n", child);
245
246     hr = IDxDiagContainer_GetChildContainer(pddc, container, NULL);
247     ok(hr == E_INVALIDARG,
248        "Expected IDxDiagContainer::GetChildContainer to return E_INVALIDARG, got 0x%08x\n", hr);
249
250     child = (void*)0xdeadbeef;
251     hr = IDxDiagContainer_GetChildContainer(pddc, container, &child);
252     ok(hr == E_INVALIDARG,
253        "Expected IDxDiagContainer::GetChildContainer to return E_INVALIDARG, got 0x%08x\n", hr);
254     ok(child == NULL, "Expected output pointer to be NULL, got %p\n", child);
255
256     /* Get the name of a suitable child container. */
257     hr = IDxDiagContainer_EnumChildContainerNames(pddc, 0, container, sizeof(container)/sizeof(WCHAR));
258     ok(hr == S_OK,
259        "Expected IDxDiagContainer::EnumChildContainerNames to return S_OK, got 0x%08x\n", hr);
260     if (FAILED(hr))
261     {
262         skip("IDxDiagContainer::EnumChildContainerNames failed\n");
263         goto cleanup;
264     }
265
266     child = (void*)0xdeadbeef;
267     hr = IDxDiagContainer_GetChildContainer(pddc, container, &child);
268     ok(hr == S_OK,
269        "Expected IDxDiagContainer::GetChildContainer to return S_OK, got 0x%08x\n", hr);
270     ok(child != NULL && child != (void*)0xdeadbeef, "Expected a valid output pointer, got %p\n", child);
271
272     if (SUCCEEDED(hr))
273     {
274         IDxDiagContainer *ptr;
275
276         /* Show that IDxDiagContainer::GetChildContainer returns a different pointer
277          * for multiple calls for the same container name. */
278         hr = IDxDiagContainer_GetChildContainer(pddc, container, &ptr);
279         ok(hr == S_OK,
280            "Expected IDxDiagContainer::GetChildContainer to return S_OK, got 0x%08x\n", hr);
281         if (SUCCEEDED(hr))
282             todo_wine ok(ptr != child, "Expected the two pointers (%p vs. %p) to be unequal", child, ptr);
283
284         IDxDiagContainer_Release(ptr);
285         IDxDiagContainer_Release(child);
286     }
287
288 cleanup:
289     IDxDiagContainer_Release(pddc);
290     IDxDiagProvider_Release(pddp);
291 }
292
293 static void test_dot_parsing(void)
294 {
295     HRESULT hr;
296     WCHAR containerbufW[256] = {0}, childbufW[256] = {0};
297     DWORD count, index;
298     size_t i;
299     static const struct
300     {
301         const char *format;
302         const HRESULT expect;
303     } test_strings[] = {
304         { "%s.%s",   S_OK },
305         { "%s.%s.",  S_OK },
306         { ".%s.%s",  E_INVALIDARG },
307         { "%s.%s..", E_INVALIDARG },
308         { ".%s.%s.", E_INVALIDARG },
309         { "..%s.%s", E_INVALIDARG },
310     };
311
312     if (!create_root_IDxDiagContainer())
313     {
314         skip("Unable to create the root IDxDiagContainer\n");
315         return;
316     }
317
318     /* Find a container with a child container of its own. */
319     hr = IDxDiagContainer_GetNumberOfChildContainers(pddc, &count);
320     ok(hr == S_OK, "Expected IDxDiagContainer::GetNumberOfChildContainers to return S_OK, got 0x%08x\n", hr);
321     if (FAILED(hr))
322     {
323         skip("IDxDiagContainer::GetNumberOfChildContainers failed\n");
324         goto cleanup;
325     }
326
327     for (index = 0; index < count; index++)
328     {
329         IDxDiagContainer *child;
330
331         hr = IDxDiagContainer_EnumChildContainerNames(pddc, index, containerbufW, sizeof(containerbufW)/sizeof(WCHAR));
332         ok(hr == S_OK, "Expected IDxDiagContainer_EnumChildContainerNames to return S_OK, got 0x%08x\n", hr);
333         if (FAILED(hr))
334         {
335             skip("IDxDiagContainer::EnumChildContainerNames failed\n");
336             goto cleanup;
337         }
338
339         hr = IDxDiagContainer_GetChildContainer(pddc, containerbufW, &child);
340         ok(hr == S_OK, "Expected IDxDiagContainer::GetChildContainer to return S_OK, got 0x%08x\n", hr);
341
342         if (SUCCEEDED(hr))
343         {
344             hr = IDxDiagContainer_EnumChildContainerNames(child, 0, childbufW, sizeof(childbufW)/sizeof(WCHAR));
345             ok(hr == S_OK || hr == E_INVALIDARG,
346                "Expected IDxDiagContainer::EnumChildContainerNames to return S_OK or E_INVALIDARG, got 0x%08x\n", hr);
347             IDxDiagContainer_Release(child);
348
349             if (SUCCEEDED(hr))
350                 break;
351         }
352     }
353
354     if (!*containerbufW || !*childbufW)
355     {
356         skip("Unable to find a suitable container\n");
357         goto cleanup;
358     }
359
360     trace("Testing IDxDiagContainer::GetChildContainer dot parsing with container %s and child container %s.\n",
361           wine_dbgstr_w(containerbufW), wine_dbgstr_w(childbufW));
362
363     for (i = 0; i < sizeof(test_strings)/sizeof(test_strings[0]); i++)
364     {
365         IDxDiagContainer *child;
366         char containerbufA[256];
367         char childbufA[256];
368         char dotbufferA[255 + 255 + 3 + 1];
369         WCHAR dotbufferW[255 + 255 + 3 + 1]; /* containerbuf + childbuf + dots + null terminator */
370
371         WideCharToMultiByte(CP_ACP, 0, containerbufW, -1, containerbufA, sizeof(containerbufA), NULL, NULL);
372         WideCharToMultiByte(CP_ACP, 0, childbufW, -1, childbufA, sizeof(childbufA), NULL, NULL);
373         sprintf(dotbufferA, test_strings[i].format, containerbufA, childbufA);
374         MultiByteToWideChar(CP_ACP, 0, dotbufferA, -1, dotbufferW, sizeof(dotbufferW)/sizeof(WCHAR));
375
376         trace("Trying container name %s\n", wine_dbgstr_w(dotbufferW));
377         hr = IDxDiagContainer_GetChildContainer(pddc, dotbufferW, &child);
378         ok(hr == test_strings[i].expect,
379            "Expected IDxDiagContainer::GetChildContainer to return 0x%08x for %s, got 0x%08x\n",
380            test_strings[i].expect, wine_dbgstr_w(dotbufferW), hr);
381         if (SUCCEEDED(hr))
382             IDxDiagContainer_Release(child);
383     }
384
385 cleanup:
386     IDxDiagContainer_Release(pddc);
387     IDxDiagProvider_Release(pddp);
388 }
389
390 static void test_EnumPropNames(void)
391 {
392     HRESULT hr;
393     WCHAR container[256], property[256];
394     IDxDiagContainer *child = NULL;
395     DWORD count, index, propcount;
396     static const WCHAR testW[] = {'t','e','s','t',0};
397
398     if (!create_root_IDxDiagContainer())
399     {
400         skip("Unable to create the root IDxDiagContainer\n");
401         return;
402     }
403
404     /* Find a container with a non-zero number of properties. */
405     hr = IDxDiagContainer_GetNumberOfChildContainers(pddc, &count);
406     ok(hr == S_OK, "Expected IDxDiagContainer::GetNumberOfChildContainers to return S_OK, got 0x%08x\n", hr);
407     if (FAILED(hr))
408     {
409         skip("IDxDiagContainer::GetNumberOfChildContainers failed\n");
410         goto cleanup;
411     }
412
413     for (index = 0; index < count; index++)
414     {
415         hr = IDxDiagContainer_EnumChildContainerNames(pddc, index, container, sizeof(container)/sizeof(WCHAR));
416         ok(hr == S_OK, "Expected IDxDiagContainer_EnumChildContainerNames to return S_OK, got 0x%08x\n", hr);
417         if (FAILED(hr))
418         {
419             skip("IDxDiagContainer::EnumChildContainerNames failed\n");
420             goto cleanup;
421         }
422
423         hr = IDxDiagContainer_GetChildContainer(pddc, container, &child);
424         ok(hr == S_OK, "Expected IDxDiagContainer::GetChildContainer to return S_OK, got 0x%08x\n", hr);
425
426         if (SUCCEEDED(hr))
427         {
428             hr = IDxDiagContainer_GetNumberOfProps(child, &propcount);
429             ok(hr == S_OK, "Expected IDxDiagContainer::GetNumberOfProps to return S_OK, got 0x%08x\n", hr);
430
431             if (!propcount)
432             {
433                 IDxDiagContainer_Release(child);
434                 child = NULL;
435             }
436             else
437                 break;
438         }
439     }
440
441     if (!child)
442     {
443         skip("Unable to find a container with non-zero property count\n");
444         goto cleanup;
445     }
446
447     hr = IDxDiagContainer_EnumPropNames(child, ~0, NULL, 0);
448     ok(hr == E_INVALIDARG, "Expected IDxDiagContainer::EnumPropNames to return E_INVALIDARG, got 0x%08x\n", hr);
449
450     memcpy(property, testW, sizeof(testW));
451     hr = IDxDiagContainer_EnumPropNames(child, ~0, property, 0);
452     ok(hr == E_INVALIDARG, "Expected IDxDiagContainer::EnumPropNames to return E_INVALIDARG, got 0x%08x\n", hr);
453     ok(!memcmp(property, testW, sizeof(testW)),
454        "Expected the property buffer to be unchanged, got %s\n", wine_dbgstr_w(property));
455
456     memcpy(property, testW, sizeof(testW));
457     hr = IDxDiagContainer_EnumPropNames(child, ~0, property, sizeof(property)/sizeof(WCHAR));
458     ok(hr == E_INVALIDARG, "Expected IDxDiagContainer::EnumPropNames to return E_INVALIDARG, got 0x%08x\n", hr);
459     ok(!memcmp(property, testW, sizeof(testW)),
460        "Expected the property buffer to be unchanged, got %s\n", wine_dbgstr_w(property));
461
462     trace("Starting property enumeration of the %s container:\n", wine_dbgstr_w(container));
463
464     /* We should be able to enumerate as many properties as the value that
465      * IDxDiagContainer::GetNumberOfProps returns. */
466     for (index = 0; index <= propcount; index++)
467     {
468         /* A buffer size of 1 is unlikely to be valid, as only a null terminator
469          * could be stored, and it is unlikely that a property name could be empty. */
470         DWORD buffersize = 1;
471
472         memcpy(property, testW, sizeof(testW));
473         hr = IDxDiagContainer_EnumPropNames(child, index, property, buffersize);
474         if (hr == E_INVALIDARG)
475         {
476             /* We should get here when index is one more than the maximum index value. */
477             ok(propcount == index,
478                "Expected IDxDiagContainer::EnumPropNames to return E_INVALIDARG "
479                "on the last index %d, got 0x%08x\n", index, hr);
480             ok(!memcmp(property, testW, sizeof(testW)),
481                "Expected the property buffer to be unchanged, got %s\n", wine_dbgstr_w(property));
482             break;
483         }
484         else if (hr == DXDIAG_E_INSUFFICIENT_BUFFER)
485         {
486             WCHAR temp[256];
487
488             ok(property[0] == '\0',
489                "Expected the property buffer string to be empty, got %s\n", wine_dbgstr_w(property));
490             hr = IDxDiagContainer_EnumPropNames(child, index, temp, sizeof(temp)/sizeof(WCHAR));
491             ok(hr == S_OK,
492                "Expected IDxDiagContainer::EnumPropNames to return S_OK, got 0x%08x\n", hr);
493
494             /* Show that the DirectX SDK's stipulation that the buffer be at
495              * least 256 characters long is a mere suggestion, and smaller sizes
496              * can be acceptable also. IDxDiagContainer::EnumPropNames doesn't
497              * provide a way of getting the exact size required, so the buffersize
498              * value will be iterated to at most 256 characters. */
499             for (buffersize = 2; buffersize <= 256; buffersize++)
500             {
501                 memcpy(property, testW, sizeof(testW));
502                 hr = IDxDiagContainer_EnumPropNames(child, index, property, buffersize);
503                 if (hr != DXDIAG_E_INSUFFICIENT_BUFFER)
504                     break;
505
506                 ok(!memcmp(temp, property, sizeof(WCHAR)*(buffersize - 1)),
507                    "Expected truncated property name string, got %s\n", wine_dbgstr_w(property));
508             }
509
510             ok(hr == S_OK,
511                "Expected IDxDiagContainer::EnumPropNames to return S_OK, "
512                "got hr = 0x%08x, buffersize = %d\n", hr, buffersize);
513             if (hr == S_OK)
514                 trace("child[%d] = %s, length = %d\n", index, wine_dbgstr_w(property), buffersize);
515         }
516         else
517         {
518             ok(0, "IDxDiagContainer::EnumPropNames unexpectedly returned 0x%08x\n", hr);
519             break;
520         }
521     }
522
523     IDxDiagContainer_Release(child);
524
525 cleanup:
526     IDxDiagContainer_Release(pddc);
527     IDxDiagProvider_Release(pddp);
528 }
529
530 START_TEST(container)
531 {
532     CoInitialize(NULL);
533     test_GetNumberOfChildContainers();
534     test_GetNumberOfProps();
535     test_EnumChildContainerNames();
536     test_GetChildContainer();
537     test_dot_parsing();
538     test_EnumPropNames();
539     CoUninitialize();
540 }