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