2 * General still image implementation
4 * Copyright 2009 Damjan Jovanovic
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.
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.
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
32 #include "wine/test.h"
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
);
39 static BOOL aggregator_addref_called
;
41 static HRESULT WINAPI
aggregator_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppvObject
)
46 static ULONG WINAPI
aggregator_AddRef(IUnknown
*iface
)
48 aggregator_addref_called
= TRUE
;
52 static ULONG WINAPI
aggregator_Release(IUnknown
*iface
)
57 static struct IUnknownVtbl aggregator_vtbl
=
59 aggregator_QueryInterface
,
64 static BOOL
init_function_pointers(void)
66 sti_dll
= LoadLibrary("sti.dll");
69 pStiCreateInstance
= (void*)
70 GetProcAddress(sti_dll
, "StiCreateInstance");
71 pStiCreateInstanceA
= (void*)
72 GetProcAddress(sti_dll
, "StiCreateInstanceA");
73 pStiCreateInstanceW
= (void*)
74 GetProcAddress(sti_dll
, "StiCreateInstanceW");
80 static void test_version_flag_versus_aw(void)
84 /* Who wins, the STI_VERSION_FLAG_UNICODE or the A/W function? And what about the neutral StiCreateInstance function? */
86 if (pStiCreateInstance
)
89 hr
= pStiCreateInstance(GetModuleHandle(NULL
), STI_VERSION_REAL
, &pStiW
, NULL
);
93 hr
= IUnknown_QueryInterface((IUnknown
*)pStiW
, &IID_IStillImageW
, (void**)&pUnknown
);
96 ok(pUnknown
== (IUnknown
*)pStiW
, "created interface was not IID_IStillImageW\n");
97 IUnknown_Release(pUnknown
);
99 IUnknown_Release((IUnknown
*)pStiW
);
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
);
107 hr
= IUnknown_QueryInterface((IUnknown
*)pStiW
, &IID_IStillImageW
, (void**)&pUnknown
);
110 ok(pUnknown
== (IUnknown
*)pStiW
, "created interface was not IID_IStillImageW\n");
111 IUnknown_Release(pUnknown
);
113 IUnknown_Release((IUnknown
*)pStiW
);
116 ok(0, "could not create StillImageW, hr = 0x%X\n", hr
);
119 skip("No StiCreateInstance function\n");
121 if (pStiCreateInstanceA
)
124 hr
= pStiCreateInstanceA(GetModuleHandle(NULL
), STI_VERSION_REAL
| STI_VERSION_FLAG_UNICODE
, &pStiA
, NULL
);
128 hr
= IUnknown_QueryInterface((IUnknown
*)pStiA
, &IID_IStillImageA
, (void**)&pUnknown
);
131 ok(pUnknown
== (IUnknown
*)pStiA
, "created interface was not IID_IStillImageA\n");
132 IUnknown_Release(pUnknown
);
134 IUnknown_Release((IUnknown
*)pStiA
);
137 todo_wine
ok(0, "could not create StillImageA, hr = 0x%X\n", hr
);
140 skip("No StiCreateInstanceA function\n");
142 if (pStiCreateInstanceW
)
145 hr
= pStiCreateInstanceW(GetModuleHandle(NULL
), STI_VERSION_REAL
, &pStiW
, NULL
);
149 hr
= IUnknown_QueryInterface((IUnknown
*)pStiW
, &IID_IStillImageW
, (void**)&pUnknown
);
152 ok(pUnknown
== (IUnknown
*)pStiW
, "created interface was not IID_IStillImageW\n");
153 IUnknown_Release((IUnknown
*)pUnknown
);
155 IUnknown_Release((IUnknown
*)pStiW
);
158 ok(0, "could not create StillImageW, hr = 0x%X\n", hr
);
161 skip("No StiCreateInstanceW function\n");
164 static void test_stillimage_aggregation(void)
166 if (pStiCreateInstanceW
)
168 IUnknown aggregator
= { &aggregator_vtbl
};
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? */
178 hr
= pStiCreateInstanceW(GetModuleHandle(NULL
), STI_VERSION_REAL
, &pStiW
, &aggregator
);
181 IStillImageW
*pStiW2
= NULL
;
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
);
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. */
194 /* And what about the IStillImageW interface? */
195 hr
= IStillImage_QueryInterface(pStiW
, &IID_IStillImageW
, (void**)&pStiW2
);
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
);
207 ok(0, "could not query for IID_IStillImageW, hr = 0x%x\n", hr
);
209 IStillImage_Release(pStiW
);
212 ok(0, "could not create StillImageW, hr = 0x%X\n", hr
);
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");
219 IStillImage_Release(pStiW
);
220 hr
= CoCreateInstance(&CLSID_Sti
, &aggregator
, CLSCTX_ALL
, &IID_IUnknown
, (void**)&pUnknown
);
222 broken(hr
== CLASS_E_NOAGGREGATION
), /* Win 2000 */
223 "CoCreateInstance unexpectedly failed when querying for IUnknown during aggregation, hr = 0x%x\n", hr
);
225 IUnknown_Release(pUnknown
);
228 skip("No StiCreateInstanceW function\n");
231 static void test_launch_app_registry(void)
233 static WCHAR appName
[] = {'w','i','n','e','s','t','i','t','e','s','t','a','p','p',0};
234 IStillImageW
*pStiW
= NULL
;
237 if (pStiCreateInstanceW
== NULL
)
239 win_skip("No StiCreateInstanceW function\n");
243 hr
= pStiCreateInstance(GetModuleHandle(NULL
), STI_VERSION_REAL
| STI_VERSION_FLAG_UNICODE
, &pStiW
, NULL
);
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
))
251 hr
= IStillImage_UnregisterLaunchApplication(pStiW
, appName
);
252 ok(SUCCEEDED(hr
), "could not unregister launch application, error 0x%X\n", hr
);
255 ok(0, "could not register launch application, error 0x%X\n", hr
);
256 IStillImage_Release(pStiW
);
259 ok(0, "could not create StillImageW, hr = 0x%X\n", hr
);
264 if (SUCCEEDED(CoInitialize(NULL
)))
266 if (init_function_pointers())
268 test_version_flag_versus_aw();
269 test_stillimage_aggregation();
270 test_launch_app_registry();
271 FreeLibrary(sti_dll
);
274 skip("could not load sti.dll\n");
278 skip("CoInitialize failed\n");