3#include <winpr/error.h>
4#include <winpr/thread.h>
6#include <freerdp/freerdp.h>
17 (void)fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, #cond); \
29static HRESULT source_get(
void* custom, UINT64 remoteHwnd,
WTS_WINDOW_INFO* info)
33 if ((s->sessionType == WTS_RDP_SESSION_TYPE_REMOTEAPP) && (remoteHwnd != 7))
35 info->hwnd = (HWND)(UINT_PTR)0xabc;
36 info->remoteWidth = info->viewWidth = s->width;
37 info->remoteHeight = info->viewHeight = 600;
42static UINT32 source_type(
void* custom)
44 return ((Source*)custom)->sessionType;
59 Listener* l = (Listener*)This;
61 l->lastWidth = info->viewWidth;
67 .OnWindowChanged = Listener_OnWindowChanged,
70static void Listener_free(wComBase*
object)
75static Source source = { 800, WTS_RDP_SESSION_TYPE_DESKTOP, 0 };
77static void client_context_free(freerdp* instance, rdpContext* context)
79 WINPR_UNUSED(instance);
80 freerdp_client_window_info_service_detach(context->windowInfoService);
81 WINPR_COM_RELEASE(context->windowInfoService);
82 context->windowInfoService =
nullptr;
85int TestClientWindowInfoService(
int argc,
char* argv[])
93 freerdp* instance =
nullptr;
94 Listener l1 = WINPR_C_ARRAY_INIT;
95 Listener l2 = WINPR_C_ARRAY_INIT;
103 svc = freerdp_client_window_info_service_new(&src);
106 CHECK(SUCCEEDED(svc->lpVtbl->GetWindowInfo(svc, 0, &info)));
107 CHECK(info.hwnd == (HWND)(UINT_PTR)0xabc && info.viewWidth == 800);
109 CHECK(SUCCEEDED(svc->lpVtbl->GetProcessId(svc, &pid)) && pid == GetCurrentProcessId());
111 CHECK(SUCCEEDED(svc->lpVtbl->GetRdpSessionType(svc, &type)) && type == 0);
114 freerdp_client_window_info_service_changed(svc, 0);
115 CHECK(svc->lpVtbl->UnsubscribeWindowChanged(svc) == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
116 CHECK(SUCCEEDED(svc->lpVtbl->SubscribeWindowChanged(svc, 0, cb1)));
117 CHECK(svc->lpVtbl->SubscribeWindowChanged(svc, 0, cb2) ==
118 HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS));
120 freerdp_client_window_info_service_changed(svc, 0);
121 CHECK(l1.calls == 1 && l1.lastWidth == 1024 && l2.calls == 0);
122 CHECK(SUCCEEDED(svc->lpVtbl->UnsubscribeWindowChanged(svc)));
123 freerdp_client_window_info_service_changed(svc, 0);
124 CHECK(l1.calls == 1);
127 freerdp_client_window_info_service_detach(svc);
128 const int calls = source.calls;
129 CHECK(svc->lpVtbl->GetWindowInfo(svc, 0, &info) == E_UNEXPECTED);
130 CHECK(svc->lpVtbl->GetRdpSessionType(svc, &type) == E_UNEXPECTED);
131 CHECK(svc->lpVtbl->SubscribeWindowChanged(svc, 0, cb1) == E_UNEXPECTED);
132 freerdp_client_window_info_service_changed(svc, 0);
133 CHECK(source.calls == calls);
134 WINPR_COM_RELEASE(svc);
138 instance = freerdp_new();
140 instance->ContextFree = client_context_free;
141 CHECK(freerdp_context_new(instance));
142 rdpContext* context = instance->context;
143 context->windowInfoService = freerdp_client_window_info_service_new(&src);
144 CHECK(context->windowInfoService);
148 CHECK(SUCCEEDED(sp->lpVtbl->GetService(sp, RDCLIENT_WINDOW_INFO_SERVICE, &unk)));
152 CHECK(SUCCEEDED(channel->lpVtbl->SubscribeWindowChanged(channel, 0, cb2)));
154 freerdp_client_window_info_service_changed(context->windowInfoService, 0);
155 CHECK(l2.calls == 1 && l2.lastWidth == 1280);
158 source.sessionType = WTS_RDP_SESSION_TYPE_REMOTEAPP;
159 CHECK(SUCCEEDED(channel->lpVtbl->GetRdpSessionType(channel, &type)) && type == 1);
160 CHECK(channel->lpVtbl->GetWindowInfo(channel, 0, &info) == E_INVALIDARG);
161 CHECK(SUCCEEDED(channel->lpVtbl->GetWindowInfo(channel, 7, &info)));
162 freerdp_client_window_info_service_changed(context->windowInfoService, 7);
163 CHECK(l2.calls == 2);
166 freerdp_context_free(instance);
167 freerdp_free(instance);
169 CHECK(channel->lpVtbl->GetWindowInfo(channel, 7, &info) == E_UNEXPECTED);
170 CHECK(SUCCEEDED(channel->lpVtbl->UnsubscribeWindowChanged(channel)));
171 WINPR_COM_RELEASE(channel);
174 CHECK(l1.com.refCount == 1 && l2.com.refCount == 1);
178 WINPR_COM_RELEASE(svc);
180 WINPR_COM_RELEASE(channel);
183 freerdp_context_free(instance);
184 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)
what the client gives the service to answer from