3#include <winpr/error.h>
5#include <freerdp/freerdp.h>
16 (void)fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, #cond); \
32static FakeWindowInfo fakeWindowInfo;
40 WINPR_UNUSED(remoteHwnd);
43 memset(info, 0,
sizeof(*info));
44 info->hwnd = (HWND)(UINT_PTR)0x1234;
45 info->remoteWidth = info->viewWidth = 1920;
46 info->remoteHeight = info->viewHeight = 1080;
63 *sessionType = WTS_RDP_SESSION_TYPE_DESKTOP;
71 FakeWindowInfo* f = (FakeWindowInfo*)This;
72 WINPR_UNUSED(remoteHwnd);
74 return HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
75 WINPR_COM_ADDREF(callback);
76 f->subscriber = callback;
83 FakeWindowInfo* f = (FakeWindowInfo*)This;
85 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
86 WINPR_COM_RELEASE(f->subscriber);
87 f->subscriber =
nullptr;
94 .GetWindowInfo = FakeWindowInfo_GetWindowInfo,
95 .GetProcessId = FakeWindowInfo_GetProcessId,
96 .GetRdpSessionType = FakeWindowInfo_GetRdpSessionType,
97 .SubscribeWindowChanged = FakeWindowInfo_Subscribe,
98 .UnsubscribeWindowChanged = FakeWindowInfo_Unsubscribe,
101static void FakeWindowInfo_free(wComBase*
object)
103 ((FakeWindowInfo*)
object)->freed = TRUE;
106static void fire_window_changed(
void)
111 (void)cb->lpVtbl->OnWindowChanged(cb, &info);
122static FakeBitmapRender fakeBitmapRender;
131 WINPR_UNUSED(mappingId);
132 WINPR_UNUSED(callback);
133 WINPR_UNUSED(renderer);
139 .GetMappedRenderer = FakeBitmapRender_GetMappedRenderer,
142static void FakeBitmapRender_free(wComBase*
object)
144 ((FakeBitmapRender*)
object)->freed = TRUE;
161 ((Listener*)This)->calls++;
167 .OnWindowChanged = Listener_OnWindowChanged,
170static void Listener_free(wComBase*
object)
172 WINPR_UNUSED(
object);
177static BOOL subscribedAtContextFree = TRUE;
179static void client_context_free(freerdp* instance, rdpContext* context)
181 WINPR_UNUSED(instance);
183 subscribedAtContextFree = (fakeWindowInfo.subscriber !=
nullptr);
184 WINPR_COM_RELEASE(context->windowInfoService);
185 context->windowInfoService =
nullptr;
186 WINPR_COM_RELEASE(context->bitmapRenderService);
187 context->bitmapRenderService =
nullptr;
194 if (FAILED(sp->lpVtbl->GetService(sp, RDCLIENT_WINDOW_INFO_SERVICE, &unk)))
198 return SUCCEEDED(hr) ? svc :
nullptr;
201int TestPluginServices(
int argc,
char* argv[])
209 Listener la = WINPR_C_ARRAY_INIT;
210 Listener lb = WINPR_C_ARRAY_INIT;
217 freerdp* instance = freerdp_new();
219 instance->ContextFree = client_context_free;
220 CHECK(freerdp_context_new(instance));
221 rdpContext* context = instance->context;
223 sp = freerdp_get_plugin_service_provider(context);
224 CHECK(sp && (sp == context->pluginServiceProvider));
228 CHECK(sp->lpVtbl->GetService(sp, RDCLIENT_WINDOW_INFO_SERVICE, &unk) == E_NOINTERFACE);
229 CHECK(sp->lpVtbl->GetService(sp, RDCLIENT_BITMAP_RENDER_SERVICE, &unk) == E_NOINTERFACE);
230 CHECK(sp->lpVtbl->GetService(sp, IID_IWTSPluginServiceProvider, &unk) == E_NOINTERFACE);
235 FakeWindowInfo_free);
236 winpr_com_base_init(&fakeBitmapRender.com,
"FakeBitmapRender", &FakeBitmapRender_vtbl.iunknown,
237 FakeBitmapRender_free);
242 CHECK(SUCCEEDED(sp->lpVtbl->GetService(sp, RDCLIENT_BITMAP_RENDER_SERVICE, &unk)));
243 CHECK(unk == (
wIUnknown*)&fakeBitmapRender);
247 a = get_window_info(sp);
248 b = get_window_info(sp);
249 CHECK(a && b && (a != b));
252 CHECK(SUCCEEDED(a->lpVtbl->GetWindowInfo(a, 0, &info)));
253 CHECK(info.hwnd == (HWND)(UINT_PTR)0x1234 && info.remoteWidth == 1920);
256 CHECK(SUCCEEDED(b->lpVtbl->GetProcessId(b, &pid)) && pid == 42);
257 CHECK(SUCCEEDED(b->lpVtbl->GetRdpSessionType(b, &type)) && type == 0);
260 CHECK(a->lpVtbl->UnsubscribeWindowChanged(a) == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
261 CHECK(a->lpVtbl->SubscribeWindowChanged(a, 0,
nullptr) == E_POINTER);
262 CHECK(SUCCEEDED(a->lpVtbl->SubscribeWindowChanged(a, 0, cba)));
263 CHECK(a->lpVtbl->SubscribeWindowChanged(a, 0, cbb) == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS));
264 CHECK(SUCCEEDED(b->lpVtbl->SubscribeWindowChanged(b, 0, cbb)));
265 CHECK(fakeWindowInfo.subscribes == 1);
267 fire_window_changed();
268 CHECK(la.calls == 1 && lb.calls == 1);
270 CHECK(SUCCEEDED(a->lpVtbl->UnsubscribeWindowChanged(a)));
271 CHECK(a->lpVtbl->UnsubscribeWindowChanged(a) == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
272 CHECK(fakeWindowInfo.unsubscribes == 0);
273 fire_window_changed();
274 CHECK(la.calls == 1 && lb.calls == 2);
277 CHECK(SUCCEEDED(b->lpVtbl->UnsubscribeWindowChanged(b)));
278 CHECK(fakeWindowInfo.unsubscribes == 1 && !fakeWindowInfo.subscriber);
279 CHECK(SUCCEEDED(b->lpVtbl->SubscribeWindowChanged(b, 0, cbb)));
280 CHECK(fakeWindowInfo.subscribes == 2);
283 WINPR_COM_RELEASE(b);
285 CHECK(fakeWindowInfo.unsubscribes == 2);
288 CHECK(SUCCEEDED(a->lpVtbl->SubscribeWindowChanged(a, 0, cba)));
289 CHECK(fakeWindowInfo.subscribes == 3);
290 freerdp_context_free(instance);
291 freerdp_free(instance);
293 CHECK(!subscribedAtContextFree);
294 CHECK(fakeWindowInfo.freed && fakeBitmapRender.freed);
295 CHECK(a->lpVtbl->GetWindowInfo(a, 0, &info) == E_UNEXPECTED);
296 CHECK(a->lpVtbl->SubscribeWindowChanged(a, 0, cbb) == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS));
297 CHECK(SUCCEEDED(a->lpVtbl->UnsubscribeWindowChanged(a)));
298 CHECK(a->lpVtbl->SubscribeWindowChanged(a, 0, cbb) == E_UNEXPECTED);
299 WINPR_COM_RELEASE(a);
303 CHECK(sp->lpVtbl->GetService(sp, RDCLIENT_WINDOW_INFO_SERVICE, &unk) == E_NOINTERFACE);
304 CHECK(sp->lpVtbl->GetService(sp, RDCLIENT_BITMAP_RENDER_SERVICE, &unk) == E_NOINTERFACE);
305 WINPR_COM_RELEASE(sp);
309 CHECK(la.com.refCount == 1 && lb.com.refCount == 1);
313 WINPR_COM_RELEASE(sp);
315 WINPR_COM_RELEASE(a);
317 WINPR_COM_RELEASE(b);
320 freerdp_context_free(instance);
321 freerdp_free(instance);
WINPR_API void winpr_com_base_init(wComBase *object, const char *className, const wIUnknownVtbl *vtbl, pfnwComBaseFree Free)
sets the vtable and the reference count to 1, the caller owns that first reference.
#define WINPR_COM_IUNKNOWN_THUNKS(prefix, iid)
WINPR_COM_REFCOUNT_THUNKS plus prefix_QueryInterface answering IUnknown and iid (a const IID*,...
#define WINPR_COM_IUNKNOWN_ENTRIES(prefix)
the initializer of a wIUnknownVtbl from prefix_QueryInterface (the thunk above or the object's own),...
#define WINPR_COM_QUERY_INTERFACE(obj, iid, ppv)
IUnknown calls on an interface in C form. In C++, the C++ form of wIUnknown is called directly: unkno...
#define WINPR_COM_CALL
the calling convention of COM methods (STDMETHODCALLTYPE)