22#include <freerdp/config.h>
28#include <freerdp/freerdp.h>
29#include <freerdp/constants.h>
30#include <freerdp/gdi/gdi.h>
31#include <freerdp/streamdump.h>
32#include <freerdp/utils/signal.h>
34#include <freerdp/client/file.h>
35#include <freerdp/client/cmdline.h>
36#include <freerdp/client/cliprdr.h>
37#include <freerdp/client/channels.h>
38#include <freerdp/channels/channels.h>
41#include <winpr/assert.h>
42#include <winpr/synch.h>
43#include <freerdp/log.h>
45#include "tf_channels.h"
46#include "tf_freerdp.h"
48#define TAG CLIENT_TAG("sample")
52static BOOL tf_begin_paint(rdpContext* context)
56 WINPR_ASSERT(context);
60 WINPR_ASSERT(gdi->primary);
61 WINPR_ASSERT(gdi->primary->hdc);
62 WINPR_ASSERT(gdi->primary->hdc->hwnd);
63 WINPR_ASSERT(gdi->primary->hdc->hwnd->invalid);
64 gdi->primary->hdc->hwnd->invalid->null = TRUE;
72static BOOL tf_end_paint(rdpContext* context)
76 WINPR_ASSERT(context);
80 WINPR_ASSERT(gdi->primary);
82 HGDI_DC hdc = gdi->primary->hdc;
88 WINPR_ASSERT(hwnd->invalid || (hwnd->ninvalid == 0));
90 if (hwnd->invalid->null)
96static BOOL tf_desktop_resize(rdpContext* context)
99 rdpSettings* settings = NULL;
101 WINPR_ASSERT(context);
103 settings = context->settings;
104 WINPR_ASSERT(settings);
112static BOOL tf_play_sound(rdpContext* context,
const PLAY_SOUND_UPDATE* play_sound)
115 WINPR_UNUSED(context);
116 WINPR_UNUSED(play_sound);
121static BOOL tf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags)
124 WINPR_UNUSED(context);
125 WINPR_UNUSED(led_flags);
130static BOOL tf_keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
137 "KeyboardSetImeStatus(unitId=%04" PRIx16
", imeState=%08" PRIx32
138 ", imeConvMode=%08" PRIx32
") ignored",
139 imeId, imeState, imeConvMode);
145static BOOL tf_pre_connect(freerdp* instance)
147 rdpSettings* settings = NULL;
149 WINPR_ASSERT(instance);
150 WINPR_ASSERT(instance->context);
152 settings = instance->context->settings;
153 WINPR_ASSERT(settings);
170 PubSub_SubscribeChannelConnected(instance->context->pubSub, tf_OnChannelConnectedEventHandler);
171 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
172 tf_OnChannelDisconnectedEventHandler);
186static BOOL tf_post_connect(freerdp* instance)
188 rdpContext* context = NULL;
190 if (!gdi_init(instance, PIXEL_FORMAT_XRGB32))
193 context = instance->context;
194 WINPR_ASSERT(context);
195 WINPR_ASSERT(context->update);
204 context->update->BeginPaint = tf_begin_paint;
205 context->update->EndPaint = tf_end_paint;
206 context->update->PlaySound = tf_play_sound;
207 context->update->DesktopResize = tf_desktop_resize;
208 context->update->SetKeyboardIndicators = tf_keyboard_set_indicators;
209 context->update->SetKeyboardImeStatus = tf_keyboard_set_ime_status;
216static void tf_post_disconnect(freerdp* instance)
223 if (!instance->context)
227 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
228 tf_OnChannelConnectedEventHandler);
229 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
230 tf_OnChannelDisconnectedEventHandler);
233 WINPR_UNUSED(context);
239static DWORD WINAPI tf_client_thread_proc(LPVOID arg)
241 freerdp* instance = (freerdp*)arg;
245 HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 };
246 BOOL rc = freerdp_connect(instance);
248 WINPR_ASSERT(instance->context);
249 WINPR_ASSERT(instance->context->settings);
252 result = freerdp_get_last_error(instance->context);
253 freerdp_abort_connect_context(instance->context);
254 WLog_ERR(TAG,
"Authentication only, exit status 0x%08" PRIx32
"", result);
260 result = freerdp_get_last_error(instance->context);
261 WLog_ERR(TAG,
"connection failure 0x%08" PRIx32, result);
265 while (!freerdp_shall_disconnect_context(instance->context))
267 nCount = freerdp_get_event_handles(instance->context, handles, ARRAYSIZE(handles));
271 WLog_ERR(TAG,
"freerdp_get_event_handles failed");
275 status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
277 if (status == WAIT_FAILED)
279 WLog_ERR(TAG,
"WaitForMultipleObjects failed with %" PRIu32
"", status);
283 if (!freerdp_check_event_handles(instance->context))
285 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
286 WLog_ERR(TAG,
"Failed to check FreeRDP event handles");
293 freerdp_disconnect(instance);
300static BOOL tf_client_global_init(
void)
302 if (freerdp_handle_signals() != 0)
309static void tf_client_global_uninit(
void)
313static int tf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
316 const char* str_data = freerdp_get_logon_error_info_data(data);
317 const char* str_type = freerdp_get_logon_error_info_type(type);
319 if (!instance || !instance->context)
323 WLog_INFO(TAG,
"Logon Error Info %s [%s]", str_data, str_type);
329static BOOL tf_client_new(freerdp* instance, rdpContext* context)
333 if (!instance || !context)
336 instance->PreConnect = tf_pre_connect;
337 instance->PostConnect = tf_post_connect;
338 instance->PostDisconnect = tf_post_disconnect;
339 instance->LogonErrorInfo = tf_logon_error_info;
345static void tf_client_free(freerdp* instance, rdpContext* context)
356static int tf_client_start(rdpContext* context)
359 WINPR_UNUSED(context);
363static int tf_client_stop(rdpContext* context)
366 WINPR_UNUSED(context);
370static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
372 WINPR_ASSERT(pEntryPoints);
374 ZeroMemory(pEntryPoints,
sizeof(RDP_CLIENT_ENTRY_POINTS));
375 pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION;
376 pEntryPoints->Size =
sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
377 pEntryPoints->GlobalInit = tf_client_global_init;
378 pEntryPoints->GlobalUninit = tf_client_global_uninit;
379 pEntryPoints->ContextSize =
sizeof(
tfContext);
380 pEntryPoints->ClientNew = tf_client_new;
381 pEntryPoints->ClientFree = tf_client_free;
382 pEntryPoints->ClientStart = tf_client_start;
383 pEntryPoints->ClientStop = tf_client_stop;
387int main(
int argc,
char* argv[])
390 RDP_CLIENT_ENTRY_POINTS clientEntryPoints = { 0 };
392 RdpClientEntry(&clientEntryPoints);
393 rdpContext* context = freerdp_client_context_new(&clientEntryPoints);
399 freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE);
402 rc = freerdp_client_settings_command_line_status_print(context->settings, status, argc,
407 if (!stream_dump_register_handlers(context, CONNECTION_STATE_MCS_CREATE_REQUEST, FALSE))
410 if (freerdp_client_start(context) != 0)
413 const DWORD res = tf_client_thread_proc(context->instance);
416 if (freerdp_client_stop(context) != 0)
420 freerdp_client_context_free(context);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.