xref: /reactos/modules/rostests/winetests/sti/sti.c (revision 074cec53)
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