ole32: Fix wrap-around bug in tick count comparison.
[wine] / dlls / sti / tests / sti.c
1 /*
2  *    General still image implementation
3  *
4  * Copyright 2009 Damjan Jovanovic
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 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #define COBJMACROS
26 #include <initguid.h>
27 #include <sti.h>
28 #include <guiddef.h>
29 #include <devguid.h>
30 #include <stdio.h>
31
32 #include "wine/test.h"
33
34 static HMODULE sti_dll;
35 static HRESULT (WINAPI *pStiCreateInstance)(HINSTANCE,DWORD,PSTIW*,LPUNKNOWN);
36 static HRESULT (WINAPI *pStiCreateInstanceA)(HINSTANCE,DWORD,PSTIA*,LPUNKNOWN);
37 static HRESULT (WINAPI *pStiCreateInstanceW)(HINSTANCE,DWORD,PSTIW*,LPUNKNOWN);
38
39 static BOOL aggregator_addref_called;
40
41 static HRESULT WINAPI aggregator_QueryInterface(IUnknown *iface, REFIID riid, void **ppvObject)
42 {
43     return E_NOTIMPL;
44 }
45
46 static ULONG WINAPI aggregator_AddRef(IUnknown *iface)
47 {
48     aggregator_addref_called = TRUE;
49     return 2;
50 }
51
52 static ULONG WINAPI aggregator_Release(IUnknown *iface)
53 {
54     return 1;
55 }
56
57 static struct IUnknownVtbl aggregator_vtbl =
58 {
59     aggregator_QueryInterface,
60     aggregator_AddRef,
61     aggregator_Release
62 };
63
64 static BOOL init_function_pointers(void)
65 {
66     sti_dll = LoadLibrary("sti.dll");
67     if (sti_dll)
68     {
69         pStiCreateInstance = (void*)
70             GetProcAddress(sti_dll, "StiCreateInstance");
71         pStiCreateInstanceA = (void*)
72             GetProcAddress(sti_dll, "StiCreateInstanceA");
73         pStiCreateInstanceW = (void*)
74             GetProcAddress(sti_dll, "StiCreateInstanceW");
75         return TRUE;
76     }
77     return FALSE;
78 }
79
80 static void test_version_flag_versus_aw(void)
81 {
82     HRESULT hr;
83
84     /* Who wins, the STI_VERSION_FLAG_UNICODE or the A/W function? And what about the neutral StiCreateInstance function? */
85
86     if (pStiCreateInstance)
87     {
88         PSTIW pStiW;
89         hr = pStiCreateInstance(GetModuleHandle(NULL), STI_VERSION_REAL, &pStiW, NULL);
90         if (SUCCEEDED(hr))
91         {
92             IUnknown *pUnknown;
93             hr = IUnknown_QueryInterface((IUnknown*)pStiW, &IID_IStillImageW, (void**)&pUnknown);
94             if (SUCCEEDED(hr))
95             {
96                 ok(pUnknown == (IUnknown*)pStiW, "created interface was not IID_IStillImageW\n");
97                 IUnknown_Release(pUnknown);
98             }
99             IUnknown_Release((IUnknown*)pStiW);
100         }
101         else
102             ok(0, "could not create StillImageA, hr = 0x%X\n", hr);
103         hr = pStiCreateInstance(GetModuleHandle(NULL), STI_VERSION_REAL | STI_VERSION_FLAG_UNICODE, &pStiW, NULL);
104         if (SUCCEEDED(hr))
105         {
106             IUnknown *pUnknown;
107             hr = IUnknown_QueryInterface((IUnknown*)pStiW, &IID_IStillImageW, (void**)&pUnknown);
108             if (SUCCEEDED(hr))
109             {
110                 ok(pUnknown == (IUnknown*)pStiW, "created interface was not IID_IStillImageW\n");
111                 IUnknown_Release(pUnknown);
112             }
113             IUnknown_Release((IUnknown*)pStiW);
114         }
115         else
116             ok(0, "could not create StillImageW, hr = 0x%X\n", hr);
117     }
118     else
119         skip("No StiCreateInstance function\n");
120
121     if (pStiCreateInstanceA)
122     {
123         PSTIA pStiA;
124         hr = pStiCreateInstanceA(GetModuleHandle(NULL), STI_VERSION_REAL | STI_VERSION_FLAG_UNICODE, &pStiA, NULL);
125         if (SUCCEEDED(hr))
126         {
127             IUnknown *pUnknown;
128             hr = IUnknown_QueryInterface((IUnknown*)pStiA, &IID_IStillImageA, (void**)&pUnknown);
129             if (SUCCEEDED(hr))
130             {
131                 ok(pUnknown == (IUnknown*)pStiA, "created interface was not IID_IStillImageA\n");
132                 IUnknown_Release(pUnknown);
133             }
134             IUnknown_Release((IUnknown*)pStiA);
135         }
136         else
137             todo_wine ok(0, "could not create StillImageA, hr = 0x%X\n", hr);
138     }
139     else
140         skip("No StiCreateInstanceA function\n");
141
142     if (pStiCreateInstanceW)
143     {
144         PSTIW pStiW;
145         hr = pStiCreateInstanceW(GetModuleHandle(NULL), STI_VERSION_REAL, &pStiW, NULL);
146         if (SUCCEEDED(hr))
147         {
148             IUnknown *pUnknown;
149             hr = IUnknown_QueryInterface((IUnknown*)pStiW, &IID_IStillImageW, (void**)&pUnknown);
150             if (SUCCEEDED(hr))
151             {
152                 ok(pUnknown == (IUnknown*)pStiW, "created interface was not IID_IStillImageW\n");
153                 IUnknown_Release((IUnknown*)pUnknown);
154             }
155             IUnknown_Release((IUnknown*)pStiW);
156         }
157         else
158             ok(0, "could not create StillImageW, hr = 0x%X\n", hr);
159     }
160     else
161         skip("No StiCreateInstanceW function\n");
162 }
163
164 static void test_stillimage_aggregation(void)
165 {
166     if (pStiCreateInstanceW)
167     {
168         IUnknown aggregator = { &aggregator_vtbl };
169         IStillImageW *pStiW;
170         IUnknown *pUnknown;
171         HRESULT hr;
172
173         /* When aggregating, the outer object must get the non-delegating IUnknown to be
174            able to control the inner object's reference count and query its interfaces.
175            But StiCreateInstance* only take PSTI. So how does the non-delegating IUnknown
176            come back to the outer object calling this function? */
177
178         hr = pStiCreateInstanceW(GetModuleHandle(NULL), STI_VERSION_REAL, &pStiW, &aggregator);
179         if (SUCCEEDED(hr))
180         {
181             IStillImageW *pStiW2 = NULL;
182
183             /* Does this interface delegate? */
184             aggregator_addref_called = FALSE;
185             IStillImage_AddRef(pStiW);
186             ok(!aggregator_addref_called, "the aggregated IStillImageW shouldn't delegate\n");
187             IStillImage_Release(pStiW);
188
189             /* Tests show calling IStillImageW_WriteToErrorLog on the interface segfaults on Windows, so I guess it's an IUnknown.
190                But querying for an IUnknown returns a different interface, which also delegates.
191                So much for COM being reflexive...
192                Anyway I doubt apps depend on any of this. */
193
194             /* And what about the IStillImageW interface? */
195             hr = IStillImage_QueryInterface(pStiW, &IID_IStillImageW, (void**)&pStiW2);
196             if (SUCCEEDED(hr))
197             {
198                 ok(pStiW != pStiW2, "the aggregated IStillImageW and its queried IStillImageW unexpectedly match\n");
199                 /* Does it delegate? */
200                 aggregator_addref_called = FALSE;
201                 IStillImage_AddRef(pStiW2);
202                 ok(aggregator_addref_called, "the created IStillImageW's IStillImageW should delegate\n");
203                 IStillImage_Release(pStiW2);
204                 IStillImage_Release(pStiW2);
205             }
206             else
207                 ok(0, "could not query for IID_IStillImageW, hr = 0x%x\n", hr);
208
209             IStillImage_Release(pStiW);
210         }
211         else
212             ok(0, "could not create StillImageW, hr = 0x%X\n", hr);
213
214         /* Now do the above tests prove that STI.DLL isn't picky about querying for IUnknown
215            in CoCreateInterface when aggregating? */
216         hr = CoCreateInstance(&CLSID_Sti, &aggregator, CLSCTX_ALL, &IID_IStillImageW, (void**)&pStiW);
217         ok(FAILED(hr), "CoCreateInstance unexpectedly succeeded when querying for IStillImageW during aggregation\n");
218         if (SUCCEEDED(hr))
219             IStillImage_Release(pStiW);
220         hr = CoCreateInstance(&CLSID_Sti, &aggregator, CLSCTX_ALL, &IID_IUnknown, (void**)&pUnknown);
221         ok(SUCCEEDED(hr) ||
222             broken(hr == CLASS_E_NOAGGREGATION), /* Win 2000 */
223                 "CoCreateInstance unexpectedly failed when querying for IUnknown during aggregation, hr = 0x%x\n", hr);
224         if (SUCCEEDED(hr))
225             IUnknown_Release(pUnknown);
226     }
227     else
228         skip("No StiCreateInstanceW function\n");
229 }
230
231 static void test_launch_app_registry(void)
232 {
233     static WCHAR appName[] = {'w','i','n','e','s','t','i','t','e','s','t','a','p','p',0};
234     IStillImageW *pStiW = NULL;
235     HRESULT hr;
236
237     if (pStiCreateInstanceW == NULL)
238     {
239         win_skip("No StiCreateInstanceW function\n");
240         return;
241     }
242
243     hr = pStiCreateInstance(GetModuleHandle(NULL), STI_VERSION_REAL | STI_VERSION_FLAG_UNICODE, &pStiW, NULL);
244     if (SUCCEEDED(hr))
245     {
246         hr = IStillImage_RegisterLaunchApplication(pStiW, appName, appName);
247         if (hr == E_ACCESSDENIED)
248             skip("Not authorized to register a launch application\n");
249         else if (SUCCEEDED(hr))
250         {
251             hr = IStillImage_UnregisterLaunchApplication(pStiW, appName);
252             ok(SUCCEEDED(hr), "could not unregister launch application, error 0x%X\n", hr);
253         }
254         else
255             ok(0, "could not register launch application, error 0x%X\n", hr);
256         IStillImage_Release(pStiW);
257     }
258     else
259         ok(0, "could not create StillImageW, hr = 0x%X\n", hr);
260 }
261
262 START_TEST(sti)
263 {
264     if (SUCCEEDED(CoInitialize(NULL)))
265     {
266         if (init_function_pointers())
267         {
268             test_version_flag_versus_aw();
269             test_stillimage_aggregation();
270             test_launch_app_registry();
271             FreeLibrary(sti_dll);
272         }
273         else
274             skip("could not load sti.dll\n");
275         CoUninitialize();
276     }
277     else
278         skip("CoInitialize failed\n");
279 }