FreeRDP
freerdp.c
1 
22 #include <freerdp/config.h>
23 
24 #include "settings.h"
25 
26 #include <string.h>
27 #include <stdarg.h>
28 #include <time.h>
29 
30 #include "rdp.h"
31 #include "input.h"
32 #include "update.h"
33 #include "surface.h"
34 #include "transport.h"
35 #include "connection.h"
36 #include "message.h"
37 #include <freerdp/buildflags.h>
38 #include "gateway/rpc_fault.h"
39 
40 #include <winpr/assert.h>
41 
42 #include <winpr/crt.h>
43 #include <winpr/string.h>
44 #include <winpr/stream.h>
45 #include <winpr/wtsapi.h>
46 #include <winpr/ssl.h>
47 #include <winpr/debug.h>
48 
49 #include <freerdp/freerdp.h>
50 #include <freerdp/streamdump.h>
51 #include <freerdp/error.h>
52 #include <freerdp/event.h>
53 #include <freerdp/locale/keyboard.h>
54 #include <freerdp/locale/locale.h>
55 #include <freerdp/channels/channels.h>
56 #include <freerdp/version.h>
57 #include <freerdp/log.h>
58 #include <freerdp/utils/signal.h>
59 
60 #include "../cache/pointer.h"
61 #include "utils.h"
62 
63 #define TAG FREERDP_TAG("core")
64 
65 static void sig_abort_connect(int signum, const char* signame, void* ctx)
66 {
67  rdpContext* context = (rdpContext*)ctx;
68 
69  WLog_INFO(TAG, "Signal %s [%d], terminating session %p", signame, signum, context);
70  if (context)
71  freerdp_abort_connect_context(context);
72 }
73 
85 static int freerdp_connect_begin(freerdp* instance)
86 {
87  BOOL rc = 0;
88  rdpRdp* rdp = NULL;
89  BOOL status = TRUE;
90  rdpSettings* settings = NULL;
91  UINT32 KeyboardLayout = 0;
92 
93  if (!instance)
94  return -1;
95 
96  WINPR_ASSERT(instance->context);
97 
98  /* We always set the return code to 0 before we start the connect sequence*/
99  instance->ConnectionCallbackState = CLIENT_STATE_INITIAL;
100  freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS);
101  clearChannelError(instance->context);
102  if (!utils_reset_abort(instance->context->rdp))
103  return -1;
104 
105  rdp = instance->context->rdp;
106  WINPR_ASSERT(rdp);
107 
108  settings = instance->context->settings;
109  WINPR_ASSERT(settings);
110 
111  freerdp_channels_register_instance(instance->context->channels, instance);
112 
113  if (!freerdp_settings_set_default_order_support(settings))
114  return -1;
115 
116  freerdp_add_signal_cleanup_handler(instance->context, sig_abort_connect);
117 
118  IFCALLRET(instance->PreConnect, status, instance);
119  instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED;
120 
121  freerdp_settings_print_warnings(settings);
122  if (status)
123  status = freerdp_settings_enforce_monitor_exists(settings);
124 
125  if (status)
126  status = freerdp_settings_check_client_after_preconnect(settings);
127 
128  if (status)
129  status = rdp_set_backup_settings(rdp);
130  if (status)
131  status = utils_reload_channels(instance->context);
132 
133  const UINT32 cp = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardCodePage);
134  KeyboardLayout = freerdp_get_keyboard_default_layout_for_locale(cp);
135  if (KeyboardLayout == 0)
136  KeyboardLayout = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardLayout);
137 
138  switch (KeyboardLayout)
139  {
140  case KBD_JAPANESE:
141  case KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002:
142  {
143  if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardType,
144  WINPR_KBD_TYPE_JAPANESE))
145  return -1;
146  if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardSubType, 2))
147  return -1;
148  if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardFunctionKey, 12))
149  return -1;
150  }
151  break;
152  default:
153  break;
154  }
155 
156  if (!status)
157  {
158  rdpContext* context = instance->context;
159  WINPR_ASSERT(context);
160  freerdp_set_last_error_if_not(context, FREERDP_ERROR_PRE_CONNECT_FAILED);
161 
162  WLog_Print(context->log, WLOG_ERROR, "freerdp_pre_connect failed: %s",
163  rdp_client_connection_state_string(instance->ConnectionCallbackState));
164  return 0;
165  }
166 
167  rc = rdp_client_connect(rdp);
168 
169  /* --authonly tests the connection without a UI */
170  if (freerdp_settings_get_bool(rdp->settings, FreeRDP_AuthenticationOnly))
171  {
172  rdpContext* context = rdp->context;
173  WINPR_ASSERT(context);
174  WLog_Print(context->log, WLOG_ERROR, "Authentication only, exit status %" PRId32 "", rc);
175  return 0;
176  }
177 
178  return rc ? 1 : 0;
179 }
180 
181 BOOL freerdp_connect(freerdp* instance)
182 {
183  BOOL status = FALSE;
184  ConnectionResultEventArgs e = { 0 };
185  const int rc = freerdp_connect_begin(instance);
186  rdpRdp* rdp = NULL;
187  UINT status2 = ERROR_INTERNAL_ERROR;
188 
189  WINPR_ASSERT(instance);
190  WINPR_ASSERT(instance->context);
191 
192  rdp = instance->context->rdp;
193  WINPR_ASSERT(rdp);
194  WINPR_ASSERT(rdp->settings);
195 
196  if (rc > 0)
197  /* Pointers might have changed in between */
198  {
199  rdp_update_internal* up = update_cast(rdp->update);
200 
201  if (freerdp_settings_get_bool(rdp->settings, FreeRDP_DumpRemoteFx))
202  {
203  up->pcap_rfx = pcap_open(
204  freerdp_settings_get_string(rdp->settings, FreeRDP_DumpRemoteFxFile), TRUE);
205 
206  if (up->pcap_rfx)
207  up->dump_rfx = TRUE;
208  }
209 
210  pointer_cache_register_callbacks(instance->context->update);
211  status = IFCALLRESULT(TRUE, instance->PostConnect, instance);
212  instance->ConnectionCallbackState = CLIENT_STATE_POSTCONNECT_PASSED;
213 
214  if (status)
215  status2 = freerdp_channels_post_connect(instance->context->channels, instance);
216  }
217  else
218  {
219  status2 = CHANNEL_RC_OK;
220  if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)
221  status = freerdp_reconnect(instance);
222  else
223  goto freerdp_connect_finally;
224  }
225 
226  if (!status || (status2 != CHANNEL_RC_OK) || !update_post_connect(instance->context->update))
227  {
228  rdpContext* context = instance->context;
229  WINPR_ASSERT(context);
230  WLog_Print(context->log, WLOG_ERROR, "freerdp_post_connect failed");
231 
232  freerdp_set_last_error_if_not(context, FREERDP_ERROR_POST_CONNECT_FAILED);
233 
234  status = FALSE;
235  goto freerdp_connect_finally;
236  }
237 
238  if (rdp->settings->PlayRemoteFx)
239  {
240  wStream* s = NULL;
241  rdp_update_internal* update = update_cast(instance->context->update);
242  pcap_record record = { 0 };
243 
244  WINPR_ASSERT(update);
245  update->pcap_rfx = pcap_open(rdp->settings->PlayRemoteFxFile, FALSE);
246  status = FALSE;
247 
248  if (!update->pcap_rfx)
249  goto freerdp_connect_finally;
250  else
251  update->play_rfx = TRUE;
252 
253  status = TRUE;
254 
255  while (pcap_has_next_record(update->pcap_rfx) && status)
256  {
257  pcap_get_next_record_header(update->pcap_rfx, &record);
258 
259  s = transport_take_from_pool(rdp->transport, record.length);
260  if (!s)
261  break;
262 
263  record.data = Stream_Buffer(s);
264  pcap_get_next_record_content(update->pcap_rfx, &record);
265  Stream_SetLength(s, record.length);
266  Stream_SetPosition(s, 0);
267 
268  if (!update_begin_paint(&update->common))
269  status = FALSE;
270  else
271  {
272  if (update_recv_surfcmds(&update->common, s) < 0)
273  status = FALSE;
274 
275  if (!update_end_paint(&update->common))
276  status = FALSE;
277  }
278 
279  Stream_Release(s);
280  }
281 
282  pcap_close(update->pcap_rfx);
283  update->pcap_rfx = NULL;
284  goto freerdp_connect_finally;
285  }
286 
287  if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
288  freerdp_set_last_error_log(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
289 
290  transport_set_connected_event(rdp->transport);
291 
292 freerdp_connect_finally:
293  EventArgsInit(&e, "freerdp");
294  e.result = status ? 0 : -1;
295  PubSub_OnConnectionResult(rdp->pubSub, instance->context, &e);
296 
297  if (!status)
298  freerdp_disconnect(instance);
299 
300  return status;
301 }
302 
303 BOOL freerdp_abort_connect(freerdp* instance)
304 {
305  if (!instance)
306  return FALSE;
307 
308  return freerdp_abort_connect_context(instance->context);
309 }
310 
311 BOOL freerdp_abort_connect_context(rdpContext* context)
312 {
313  if (!context)
314  return FALSE;
315 
316  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
317 
318  return utils_abort_connect(context->rdp);
319 }
320 
321 #if defined(WITH_FREERDP_DEPRECATED)
322 BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
323 {
324  rdpRdp* rdp = NULL;
325 
326  WINPR_ASSERT(instance);
327  WINPR_ASSERT(instance->context);
328 
329  rdp = instance->context->rdp;
330  WINPR_ASSERT(rdp);
331 
332  transport_get_fds(rdp->transport, rfds, rcount);
333  return TRUE;
334 }
335 #endif
336 
337 BOOL freerdp_check_fds(freerdp* instance)
338 {
339  int status = 0;
340  rdpRdp* rdp = NULL;
341 
342  if (!instance)
343  return FALSE;
344 
345  if (!instance->context)
346  return FALSE;
347 
348  if (!instance->context->rdp)
349  return FALSE;
350 
351  rdp = instance->context->rdp;
352  status = rdp_check_fds(rdp);
353 
354  if (status < 0)
355  {
356  TerminateEventArgs e;
357  rdpContext* context = instance->context;
358  WINPR_ASSERT(context);
359 
360  WLog_Print(context->log, WLOG_DEBUG, "rdp_check_fds() - %i", status);
361  EventArgsInit(&e, "freerdp");
362  e.code = 0;
363  PubSub_OnTerminate(rdp->pubSub, context, &e);
364  return FALSE;
365  }
366 
367  return TRUE;
368 }
369 
370 DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count)
371 {
372  DWORD nCount = 0;
373 
374  WINPR_ASSERT(context);
375  WINPR_ASSERT(context->rdp);
376  WINPR_ASSERT(events || (count == 0));
377 
378  nCount += transport_get_event_handles(context->rdp->transport, events, count);
379 
380  if (nCount == 0)
381  return 0;
382 
383  if (events && (nCount < count + 2))
384  {
385  events[nCount++] = freerdp_channels_get_event_handle(context->instance);
386  events[nCount++] = getChannelErrorEventHandle(context);
387  events[nCount++] = utils_get_abort_event(context->rdp);
388  }
389  else
390  return 0;
391 
392  const SSIZE_T rc = freerdp_client_channel_get_registered_event_handles(
393  context->channels, &events[nCount], count - nCount);
394  if (rc < 0)
395  return 0;
396  return nCount + (DWORD)rc;
397 }
398 
399 /* Resend mouse cursor position to prevent session lock in prevent-session-lock mode */
400 static BOOL freerdp_prevent_session_lock(rdpContext* context)
401 {
402  WINPR_ASSERT(context);
403  WINPR_ASSERT(context->input);
404 
405  rdp_input_internal* in = input_cast(context->input);
406 
407  UINT32 FakeMouseMotionInterval =
408  freerdp_settings_get_uint32(context->settings, FreeRDP_FakeMouseMotionInterval);
409  if (FakeMouseMotionInterval && in->lastInputTimestamp)
410  {
411  const time_t now = time(NULL);
412  if (WINPR_ASSERTING_INT_CAST(size_t, now) - in->lastInputTimestamp >
413  FakeMouseMotionInterval)
414  {
415  WLog_Print(context->log, WLOG_DEBUG,
416  "fake mouse move: x=%d y=%d lastInputTimestamp=%" PRIu64 " "
417  "FakeMouseMotionInterval=%" PRIu32,
418  in->lastX, in->lastY, in->lastInputTimestamp, FakeMouseMotionInterval);
419 
420  BOOL status = freerdp_input_send_mouse_event(context->input, PTR_FLAGS_MOVE, in->lastX,
421  in->lastY);
422  if (!status)
423  {
424  if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
425  WLog_Print(context->log, WLOG_ERROR,
426  "freerdp_prevent_session_lock() failed - %" PRIi32 "", status);
427 
428  return FALSE;
429  }
430 
431  return status;
432  }
433  }
434 
435  return TRUE;
436 }
437 
438 BOOL freerdp_check_event_handles(rdpContext* context)
439 {
440  WINPR_ASSERT(context);
441 
442  BOOL status = freerdp_check_fds(context->instance);
443 
444  if (!status)
445  {
446  if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
447  WLog_Print(context->log, WLOG_ERROR, "freerdp_check_fds() failed - %" PRIi32 "",
448  status);
449 
450  return FALSE;
451  }
452 
453  status = freerdp_channels_check_fds(context->channels, context->instance);
454 
455  if (!status)
456  {
457  if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
458  WLog_Print(context->log, WLOG_ERROR,
459  "freerdp_channels_check_fds() failed - %" PRIi32 "", status);
460 
461  return FALSE;
462  }
463 
464  status = checkChannelErrorEvent(context);
465 
466  if (!status)
467  {
468  if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
469  WLog_Print(context->log, WLOG_ERROR, "checkChannelErrorEvent() failed - %" PRIi32 "",
470  status);
471 
472  return FALSE;
473  }
474 
475  status = freerdp_prevent_session_lock(context);
476 
477  return status;
478 }
479 
480 wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD id)
481 {
482  wMessageQueue* queue = NULL;
483 
484  WINPR_ASSERT(instance);
485 
486  rdpContext* context = instance->context;
487  WINPR_ASSERT(context);
488 
489  switch (id)
490  {
491  case FREERDP_UPDATE_MESSAGE_QUEUE:
492  {
493  rdp_update_internal* update = update_cast(context->update);
494  queue = update->queue;
495  }
496  break;
497 
498  case FREERDP_INPUT_MESSAGE_QUEUE:
499  {
500  rdp_input_internal* input = input_cast(context->input);
501  queue = input->queue;
502  }
503  break;
504  default:
505  break;
506  }
507 
508  return queue;
509 }
510 
511 HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD id)
512 {
513  HANDLE event = NULL;
514  wMessageQueue* queue = freerdp_get_message_queue(instance, id);
515 
516  if (queue)
517  event = MessageQueue_Event(queue);
518 
519  return event;
520 }
521 
522 int freerdp_message_queue_process_message(freerdp* instance, DWORD id, wMessage* message)
523 {
524  int status = -1;
525  rdpContext* context = NULL;
526 
527  WINPR_ASSERT(instance);
528 
529  context = instance->context;
530  WINPR_ASSERT(context);
531 
532  switch (id)
533  {
534  case FREERDP_UPDATE_MESSAGE_QUEUE:
535  status = update_message_queue_process_message(context->update, message);
536  break;
537 
538  case FREERDP_INPUT_MESSAGE_QUEUE:
539  status = input_message_queue_process_message(context->input, message);
540  break;
541  default:
542  break;
543  }
544 
545  return status;
546 }
547 
548 int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD id)
549 {
550  int status = -1;
551  rdpContext* context = NULL;
552 
553  WINPR_ASSERT(instance);
554 
555  context = instance->context;
556  WINPR_ASSERT(context);
557 
558  switch (id)
559  {
560  case FREERDP_UPDATE_MESSAGE_QUEUE:
561  status = update_message_queue_process_pending_messages(context->update);
562  break;
563 
564  case FREERDP_INPUT_MESSAGE_QUEUE:
565  status = input_message_queue_process_pending_messages(context->input);
566  break;
567  default:
568  break;
569  }
570 
571  return status;
572 }
573 
574 static BOOL freerdp_send_channel_data(freerdp* instance, UINT16 channelId, const BYTE* data,
575  size_t size)
576 {
577  WINPR_ASSERT(instance);
578  WINPR_ASSERT(instance->context);
579  WINPR_ASSERT(instance->context->rdp);
580  return rdp_send_channel_data(instance->context->rdp, channelId, data, size);
581 }
582 
583 static BOOL freerdp_send_channel_packet(freerdp* instance, UINT16 channelId, size_t totalSize,
584  UINT32 flags, const BYTE* data, size_t chunkSize)
585 {
586  WINPR_ASSERT(instance);
587  WINPR_ASSERT(instance->context);
588  WINPR_ASSERT(instance->context->rdp);
589  return rdp_channel_send_packet(instance->context->rdp, channelId, totalSize, flags, data,
590  chunkSize);
591 }
592 
593 BOOL freerdp_disconnect(freerdp* instance)
594 {
595  BOOL rc = TRUE;
596  rdpRdp* rdp = NULL;
597  rdp_update_internal* up = NULL;
598 
599  if (!instance || !instance->context)
600  return FALSE;
601 
602  rdp = instance->context->rdp;
603  utils_abort_connect(rdp);
604 
605  if (!rdp_client_disconnect(rdp))
606  rc = FALSE;
607 
608  up = update_cast(rdp->update);
609 
610  update_post_disconnect(rdp->update);
611 
612  IFCALL(instance->PostDisconnect, instance);
613 
614  if (up->pcap_rfx)
615  {
616  up->dump_rfx = FALSE;
617  pcap_close(up->pcap_rfx);
618  up->pcap_rfx = NULL;
619  }
620 
621  freerdp_channels_close(instance->context->channels, instance);
622 
623  IFCALL(instance->PostFinalDisconnect, instance);
624 
625  freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
626  return rc;
627 }
628 
629 BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
630 {
631  WINPR_ASSERT(instance);
632  return freerdp_disconnect_before_reconnect_context(instance->context);
633 }
634 
635 BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
636 {
637  rdpRdp* rdp = NULL;
638 
639  WINPR_ASSERT(context);
640 
641  rdp = context->rdp;
642  return rdp_client_disconnect_and_clear(rdp);
643 }
644 
645 BOOL freerdp_reconnect(freerdp* instance)
646 {
647  rdpRdp* rdp = NULL;
648 
649  WINPR_ASSERT(instance);
650  WINPR_ASSERT(instance->context);
651 
652  if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
653  return FALSE;
654 
655  rdp = instance->context->rdp;
656 
657  if (!utils_reset_abort(instance->context->rdp))
658  return FALSE;
659  return rdp_client_reconnect(rdp);
660 }
661 
662 BOOL freerdp_shall_disconnect(freerdp* instance)
663 {
664  if (!instance)
665  return FALSE;
666 
667  return freerdp_shall_disconnect_context(instance->context);
668 }
669 
670 BOOL freerdp_shall_disconnect_context(const rdpContext* context)
671 {
672  if (!context)
673  return FALSE;
674 
675  return utils_abort_event_is_set(context->rdp);
676 }
677 
678 BOOL freerdp_focus_required(freerdp* instance)
679 {
680  rdpRdp* rdp = NULL;
681  BOOL bRetCode = FALSE;
682 
683  WINPR_ASSERT(instance);
684  WINPR_ASSERT(instance->context);
685 
686  rdp = instance->context->rdp;
687  WINPR_ASSERT(rdp);
688 
689  if (rdp->resendFocus)
690  {
691  bRetCode = TRUE;
692  rdp->resendFocus = FALSE;
693  }
694 
695  return bRetCode;
696 }
697 
698 void freerdp_set_focus(freerdp* instance)
699 {
700  rdpRdp* rdp = NULL;
701 
702  WINPR_ASSERT(instance);
703  WINPR_ASSERT(instance->context);
704 
705  rdp = instance->context->rdp;
706  WINPR_ASSERT(rdp);
707 
708  rdp->resendFocus = TRUE;
709 }
710 
711 void freerdp_get_version(int* major, int* minor, int* revision)
712 {
713  if (major != NULL)
714  *major = FREERDP_VERSION_MAJOR;
715 
716  if (minor != NULL)
717  *minor = FREERDP_VERSION_MINOR;
718 
719  if (revision != NULL)
720  *revision = FREERDP_VERSION_REVISION;
721 }
722 
723 const char* freerdp_get_version_string(void)
724 {
725  return FREERDP_VERSION_FULL;
726 }
727 
728 const char* freerdp_get_build_config(void)
729 {
730  WINPR_PRAGMA_DIAG_PUSH
731  WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
732  static const char build_config[] =
733  "Build configuration: " FREERDP_BUILD_CONFIG "\n"
734  "Build type: " FREERDP_BUILD_TYPE "\n"
735  "CFLAGS: " FREERDP_CFLAGS "\n"
736  "Compiler: " FREERDP_COMPILER_ID ", " FREERDP_COMPILER_VERSION "\n"
737  "Target architecture: " FREERDP_TARGET_ARCH "\n";
738  WINPR_PRAGMA_DIAG_POP
739  return build_config;
740 }
741 
742 const char* freerdp_get_build_revision(void)
743 {
744  return FREERDP_GIT_REVISION;
745 }
746 
747 static wEventType FreeRDP_Events[] = {
748  DEFINE_EVENT_ENTRY(WindowStateChange), DEFINE_EVENT_ENTRY(ResizeWindow),
749  DEFINE_EVENT_ENTRY(LocalResizeWindow), DEFINE_EVENT_ENTRY(EmbedWindow),
750  DEFINE_EVENT_ENTRY(PanningChange), DEFINE_EVENT_ENTRY(ZoomingChange),
751  DEFINE_EVENT_ENTRY(ErrorInfo), DEFINE_EVENT_ENTRY(Terminate),
752  DEFINE_EVENT_ENTRY(ConnectionResult), DEFINE_EVENT_ENTRY(ChannelConnected),
753  DEFINE_EVENT_ENTRY(ChannelDisconnected), DEFINE_EVENT_ENTRY(MouseEvent),
754  DEFINE_EVENT_ENTRY(Activated), DEFINE_EVENT_ENTRY(Timer),
755  DEFINE_EVENT_ENTRY(GraphicsReset)
756 };
757 
768 BOOL freerdp_context_new(freerdp* instance)
769 {
770  return freerdp_context_new_ex(instance, NULL);
771 }
772 
773 BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
774 {
775  rdpRdp* rdp = NULL;
776  rdpContext* context = NULL;
777  BOOL ret = TRUE;
778 
779  WINPR_ASSERT(instance);
780 
781  instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
782 
783  if (!context)
784  return FALSE;
785 
786  context->log = WLog_Get(TAG);
787  if (!context->log)
788  goto fail;
789 
790  /* Set to external settings, prevents rdp_new from creating its own instance */
791  context->settings = settings;
792  context->instance = instance;
793  context->ServerMode = FALSE;
794  context->disconnectUltimatum = 0;
795 
796  context->metrics = metrics_new(context);
797 
798  if (!context->metrics)
799  goto fail;
800 
801  rdp = rdp_new(context);
802 
803  if (!rdp)
804  goto fail;
805 
806  context->rdp = rdp;
807  context->pubSub = rdp->pubSub;
808 
809  if (!context->pubSub)
810  goto fail;
811 
812  PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
813 
814 #if defined(WITH_FREERDP_DEPRECATED)
815  instance->input = rdp->input;
816  instance->update = rdp->update;
817  instance->settings = rdp->settings;
818  instance->autodetect = rdp->autodetect;
819 #endif
820 
821  instance->heartbeat = rdp->heartbeat;
822  context->graphics = graphics_new(context);
823 
824  if (!context->graphics)
825  goto fail;
826 
827  context->input = rdp->input;
828  context->update = rdp->update;
829  context->settings = rdp->settings;
830  context->autodetect = rdp->autodetect;
831 
832  if (!(context->errorDescription = calloc(1, 500)))
833  {
834  WLog_Print(context->log, WLOG_ERROR, "calloc failed!");
835  goto fail;
836  }
837 
838  if (!(context->channelErrorEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
839  {
840  WLog_Print(context->log, WLOG_ERROR, "CreateEvent failed!");
841  goto fail;
842  }
843 
844  update_register_client_callbacks(rdp->update);
845 
846  if (!(context->channels = freerdp_channels_new(instance)))
847  goto fail;
848 
849  context->dump = stream_dump_new();
850  if (!context->dump)
851  goto fail;
852 
853  IFCALLRET(instance->ContextNew, ret, instance, context);
854 
855  if (ret)
856  return TRUE;
857 
858 fail:
859  freerdp_context_free(instance);
860  return FALSE;
861 }
862 
863 BOOL freerdp_context_reset(freerdp* instance)
864 {
865  if (!instance)
866  return FALSE;
867 
868  WINPR_ASSERT(instance->context);
869  rdpRdp* rdp = instance->context->rdp;
870 
871  return rdp_reset_runtime_settings(rdp);
872 }
873 
882 void freerdp_context_free(freerdp* instance)
883 {
884  rdpContext* ctx = NULL;
885 
886  if (!instance)
887  return;
888 
889  if (!instance->context)
890  return;
891 
892  ctx = instance->context;
893 
894  IFCALL(instance->ContextFree, instance, ctx);
895  rdp_free(ctx->rdp);
896  ctx->rdp = NULL;
897  ctx->settings = NULL; /* owned by rdpRdp */
898 
899  graphics_free(ctx->graphics);
900  ctx->graphics = NULL;
901 
902  metrics_free(ctx->metrics);
903  ctx->metrics = NULL;
904 
905  if (ctx->channelErrorEvent)
906  (void)CloseHandle(ctx->channelErrorEvent);
907  ctx->channelErrorEvent = NULL;
908 
909  free(ctx->errorDescription);
910  ctx->errorDescription = NULL;
911 
912  freerdp_channels_free(ctx->channels);
913  ctx->channels = NULL;
914 
915  freerdp_client_codecs_free(ctx->codecs);
916  ctx->codecs = NULL;
917 
918  stream_dump_free(ctx->dump);
919  ctx->dump = NULL;
920 
921  ctx->input = NULL; /* owned by rdpRdp */
922  ctx->update = NULL; /* owned by rdpRdp */
923  ctx->settings = NULL; /* owned by rdpRdp */
924  ctx->autodetect = NULL; /* owned by rdpRdp */
925 
926  free(ctx);
927  instance->context = NULL;
928 #if defined(WITH_FREERDP_DEPRECATED)
929  instance->input = NULL; /* owned by rdpRdp */
930  instance->update = NULL; /* owned by rdpRdp */
931  instance->settings = NULL; /* owned by rdpRdp */
932  instance->autodetect = NULL; /* owned by rdpRdp */
933 #endif
934  instance->heartbeat = NULL; /* owned by rdpRdp */
935 }
936 
937 int freerdp_get_disconnect_ultimatum(rdpContext* context)
938 {
939  WINPR_ASSERT(context);
940  return context->disconnectUltimatum;
941 }
942 
943 UINT32 freerdp_error_info(freerdp* instance)
944 {
945  WINPR_ASSERT(instance);
946  WINPR_ASSERT(instance->context);
947  WINPR_ASSERT(instance->context->rdp);
948  return instance->context->rdp->errorInfo;
949 }
950 
951 void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
952 {
953  if (!rdp)
954  return;
955 
956  rdp_set_error_info(rdp, error);
957 }
958 
959 BOOL freerdp_send_error_info(rdpRdp* rdp)
960 {
961  if (!rdp)
962  return FALSE;
963 
964  return rdp_send_error_info(rdp);
965 }
966 
967 UINT32 freerdp_get_last_error(rdpContext* context)
968 {
969  WINPR_ASSERT(context);
970  return context->LastError;
971 }
972 
973 const char* freerdp_get_last_error_name(UINT32 code)
974 {
975  const char* name = NULL;
976  const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
977  const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
978 
979  switch (cls)
980  {
981  case FREERDP_ERROR_ERRBASE_CLASS:
982  name = freerdp_get_error_base_name(type);
983  break;
984 
985  case FREERDP_ERROR_ERRINFO_CLASS:
986  name = freerdp_get_error_info_name(type);
987  break;
988 
989  case FREERDP_ERROR_CONNECT_CLASS:
990  name = freerdp_get_error_connect_name(type);
991  break;
992 
993  default:
994  name = rpc_error_to_string(code);
995  break;
996  }
997 
998  return name;
999 }
1000 
1001 const char* freerdp_get_last_error_string(UINT32 code)
1002 {
1003  const char* string = NULL;
1004  const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1005  const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1006 
1007  switch (cls)
1008  {
1009  case FREERDP_ERROR_ERRBASE_CLASS:
1010  string = freerdp_get_error_base_string(type);
1011  break;
1012 
1013  case FREERDP_ERROR_ERRINFO_CLASS:
1014  string = freerdp_get_error_info_string(type);
1015  break;
1016 
1017  case FREERDP_ERROR_CONNECT_CLASS:
1018  string = freerdp_get_error_connect_string(type);
1019  break;
1020 
1021  default:
1022  string = rpc_error_to_string(code);
1023  break;
1024  }
1025 
1026  return string;
1027 }
1028 
1029 const char* freerdp_get_last_error_category(UINT32 code)
1030 {
1031  const char* string = NULL;
1032  const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1033  const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1034 
1035  switch (cls)
1036  {
1037  case FREERDP_ERROR_ERRBASE_CLASS:
1038  string = freerdp_get_error_base_category(type);
1039  break;
1040 
1041  case FREERDP_ERROR_ERRINFO_CLASS:
1042  string = freerdp_get_error_info_category(type);
1043  break;
1044 
1045  case FREERDP_ERROR_CONNECT_CLASS:
1046  string = freerdp_get_error_connect_category(type);
1047  break;
1048 
1049  default:
1050  string = rpc_error_to_category(code);
1051  break;
1052  }
1053 
1054  return string;
1055 }
1056 
1057 void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError, const char* fkt,
1058  const char* file, int line)
1059 {
1060  WINPR_ASSERT(context);
1061  WINPR_ASSERT(line >= 0);
1062 
1063  if (lastError)
1064  {
1065  if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1066  {
1067  WLog_PrintMessage(context->log, WLOG_MESSAGE_TEXT, WLOG_ERROR, (size_t)line, file, fkt,
1068  "%s [0x%08" PRIX32 "]", freerdp_get_last_error_name(lastError),
1069  lastError);
1070  }
1071  }
1072 
1073  if (lastError == FREERDP_ERROR_SUCCESS)
1074  {
1075  if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1076  WLog_PrintMessage(context->log, WLOG_MESSAGE_TEXT, WLOG_DEBUG, (size_t)line, file, fkt,
1077  "resetting error state");
1078  }
1079  else if (context->LastError != FREERDP_ERROR_SUCCESS)
1080  {
1081  if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1082  {
1083  WLog_PrintMessage(context->log, WLOG_MESSAGE_TEXT, WLOG_ERROR, (size_t)line, file, fkt,
1084  "TODO: Trying to set error code %s, but %s already set!",
1085  freerdp_get_last_error_name(lastError),
1086  freerdp_get_last_error_name(context->LastError));
1087  }
1088  }
1089  context->LastError = lastError;
1090 }
1091 
1092 const char* freerdp_get_logon_error_info_type_ex(UINT32 type, char* buffer, size_t size)
1093 {
1094  const char* str = freerdp_get_logon_error_info_type(type);
1095  (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, type);
1096  return buffer;
1097 }
1098 
1099 const char* freerdp_get_logon_error_info_type(UINT32 type)
1100 {
1101  switch (type)
1102  {
1103  case LOGON_MSG_DISCONNECT_REFUSED:
1104  return "LOGON_MSG_DISCONNECT_REFUSED";
1105 
1106  case LOGON_MSG_NO_PERMISSION:
1107  return "LOGON_MSG_NO_PERMISSION";
1108 
1109  case LOGON_MSG_BUMP_OPTIONS:
1110  return "LOGON_MSG_BUMP_OPTIONS";
1111 
1112  case LOGON_MSG_RECONNECT_OPTIONS:
1113  return "LOGON_MSG_RECONNECT_OPTIONS";
1114 
1115  case LOGON_MSG_SESSION_TERMINATE:
1116  return "LOGON_MSG_SESSION_TERMINATE";
1117 
1118  case LOGON_MSG_SESSION_CONTINUE:
1119  return "LOGON_MSG_SESSION_CONTINUE";
1120 
1121  default:
1122  return "UNKNOWN";
1123  }
1124 }
1125 
1126 const char* freerdp_get_logon_error_info_data(UINT32 data)
1127 {
1128  switch (data)
1129  {
1130  case LOGON_FAILED_BAD_PASSWORD:
1131  return "LOGON_FAILED_BAD_PASSWORD";
1132 
1133  case LOGON_FAILED_UPDATE_PASSWORD:
1134  return "LOGON_FAILED_UPDATE_PASSWORD";
1135 
1136  case LOGON_FAILED_OTHER:
1137  return "LOGON_FAILED_OTHER";
1138 
1139  case LOGON_WARNING:
1140  return "LOGON_WARNING";
1141 
1142  default:
1143  return "SESSION_ID";
1144  }
1145 }
1146 
1147 const char* freerdp_get_logon_error_info_data_ex(UINT32 data, char* buffer, size_t size)
1148 {
1149  const char* str = freerdp_get_logon_error_info_data(data);
1150  (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, data);
1151  return buffer;
1152 }
1153 
1157 freerdp* freerdp_new(void)
1158 {
1159  freerdp* instance = NULL;
1160  instance = (freerdp*)calloc(1, sizeof(freerdp));
1161 
1162  if (!instance)
1163  return NULL;
1164 
1165  instance->ContextSize = sizeof(rdpContext);
1166  instance->SendChannelData = freerdp_send_channel_data;
1167  instance->SendChannelPacket = freerdp_send_channel_packet;
1168  instance->ReceiveChannelData = freerdp_channels_data;
1169  return instance;
1170 }
1171 
1176 void freerdp_free(freerdp* instance)
1177 {
1178  free(instance);
1179 }
1180 
1181 ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount)
1182 {
1183  WINPR_ASSERT(context);
1184  WINPR_ASSERT(context->rdp);
1185  return transport_get_bytes_sent(context->rdp->transport, resetCount);
1186 }
1187 
1188 BOOL freerdp_nla_impersonate(rdpContext* context)
1189 {
1190  rdpNla* nla = NULL;
1191 
1192  if (!context)
1193  return FALSE;
1194 
1195  if (!context->rdp)
1196  return FALSE;
1197 
1198  if (!context->rdp->transport)
1199  return FALSE;
1200 
1201  nla = transport_get_nla(context->rdp->transport);
1202  return nla_impersonate(nla);
1203 }
1204 
1205 BOOL freerdp_nla_revert_to_self(rdpContext* context)
1206 {
1207  rdpNla* nla = NULL;
1208 
1209  if (!context)
1210  return FALSE;
1211 
1212  if (!context->rdp)
1213  return FALSE;
1214 
1215  if (!context->rdp->transport)
1216  return FALSE;
1217 
1218  nla = transport_get_nla(context->rdp->transport);
1219  return nla_revert_to_self(nla);
1220 }
1221 
1222 UINT32 freerdp_get_nla_sspi_error(rdpContext* context)
1223 {
1224  WINPR_ASSERT(context);
1225  WINPR_ASSERT(context->rdp);
1226  WINPR_ASSERT(context->rdp->transport);
1227 
1228  rdpNla* nla = transport_get_nla(context->rdp->transport);
1229 
1230  return (UINT32)nla_get_sspi_error(nla);
1231 }
1232 
1233 BOOL freerdp_nla_encrypt(rdpContext* context, const SecBuffer* inBuffer, SecBuffer* outBuffer)
1234 {
1235  WINPR_ASSERT(context);
1236  WINPR_ASSERT(context->rdp);
1237 
1238  rdpNla* nla = context->rdp->nla;
1239  return nla_encrypt(nla, inBuffer, outBuffer);
1240 }
1241 
1242 BOOL freerdp_nla_decrypt(rdpContext* context, const SecBuffer* inBuffer, SecBuffer* outBuffer)
1243 {
1244  WINPR_ASSERT(context);
1245  WINPR_ASSERT(context->rdp);
1246 
1247  rdpNla* nla = context->rdp->nla;
1248  return nla_decrypt(nla, inBuffer, outBuffer);
1249 }
1250 
1251 SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ulAttr, PVOID pBuffer)
1252 {
1253  WINPR_ASSERT(context);
1254  WINPR_ASSERT(context->rdp);
1255 
1256  return nla_QueryContextAttributes(context->rdp->nla, ulAttr, pBuffer);
1257 }
1258 
1259 HANDLE getChannelErrorEventHandle(rdpContext* context)
1260 {
1261  WINPR_ASSERT(context);
1262  return context->channelErrorEvent;
1263 }
1264 
1265 BOOL checkChannelErrorEvent(rdpContext* context)
1266 {
1267  WINPR_ASSERT(context);
1268 
1269  if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1270  {
1271  WLog_Print(context->log, WLOG_ERROR, "%s. Error was %" PRIu32 "", context->errorDescription,
1272  context->channelErrorNum);
1273  return FALSE;
1274  }
1275 
1276  return TRUE;
1277 }
1278 
1284 UINT getChannelError(rdpContext* context)
1285 {
1286  WINPR_ASSERT(context);
1287  return context->channelErrorNum;
1288 }
1289 
1290 const char* getChannelErrorDescription(rdpContext* context)
1291 {
1292  WINPR_ASSERT(context);
1293  return context->errorDescription;
1294 }
1295 
1296 void clearChannelError(rdpContext* context)
1297 {
1298  WINPR_ASSERT(context);
1299  context->channelErrorNum = 0;
1300  memset(context->errorDescription, 0, 500);
1301  (void)ResetEvent(context->channelErrorEvent);
1302 }
1303 
1304 WINPR_ATTR_FORMAT_ARG(3, 4)
1305 void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const char* format, ...)
1306 {
1307  va_list ap = { 0 };
1308  va_start(ap, format);
1309 
1310  WINPR_ASSERT(context);
1311 
1312  context->channelErrorNum = errorNum;
1313  (void)vsnprintf(context->errorDescription, 499, format, ap);
1314  va_end(ap);
1315  (void)SetEvent(context->channelErrorEvent);
1316 }
1317 
1318 const char* freerdp_nego_get_routing_token(rdpContext* context, DWORD* length)
1319 {
1320  if (!context || !context->rdp)
1321  return NULL;
1322 
1323  return (const char*)nego_get_routing_token(context->rdp->nego, length);
1324 }
1325 
1326 BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1327 {
1328  WINPR_ASSERT(context);
1329  return rdp_io_callback_set_event(context->rdp, set);
1330 }
1331 
1332 const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1333 {
1334  WINPR_ASSERT(context);
1335  return rdp_get_io_callbacks(context->rdp);
1336 }
1337 
1338 BOOL freerdp_set_io_callbacks(rdpContext* context, const rdpTransportIo* io_callbacks)
1339 {
1340  WINPR_ASSERT(context);
1341  return rdp_set_io_callbacks(context->rdp, io_callbacks);
1342 }
1343 
1344 BOOL freerdp_set_io_callback_context(rdpContext* context, void* usercontext)
1345 {
1346  WINPR_ASSERT(context);
1347  return rdp_set_io_callback_context(context->rdp, usercontext);
1348 }
1349 
1350 void* freerdp_get_io_callback_context(rdpContext* context)
1351 {
1352  WINPR_ASSERT(context);
1353  return rdp_get_io_callback_context(context->rdp);
1354 }
1355 
1356 CONNECTION_STATE freerdp_get_state(const rdpContext* context)
1357 {
1358  WINPR_ASSERT(context);
1359  return rdp_get_state(context->rdp);
1360 }
1361 
1362 const char* freerdp_state_string(CONNECTION_STATE state)
1363 {
1364  return rdp_state_string(state);
1365 }
1366 
1367 BOOL freerdp_is_active_state(const rdpContext* context)
1368 {
1369  WINPR_ASSERT(context);
1370  return rdp_is_active_state(context->rdp);
1371 }
1372 
1373 BOOL freerdp_channels_from_mcs(rdpSettings* settings, const rdpContext* context)
1374 {
1375  WINPR_ASSERT(context);
1376  return rdp_channels_from_mcs(settings, context->rdp);
1377 }
1378 
1379 HANDLE freerdp_abort_event(rdpContext* context)
1380 {
1381  WINPR_ASSERT(context);
1382  return utils_get_abort_event(context->rdp);
1383 }
1384 
1385 static void test_mcs_free(rdpMcs* mcs)
1386 {
1387  if (!mcs)
1388  return;
1389 
1390  rdpTransport* transport = mcs->transport;
1391  rdpContext* context = transport_get_context(transport);
1392  if (context)
1393  {
1394  rdpSettings* settings = context->settings;
1395  freerdp_settings_free(settings);
1396  }
1397  free(context);
1398  transport_free(transport);
1399 
1400  mcs_free(mcs);
1401 }
1402 
1403 static rdpMcs* test_mcs_new(void)
1404 {
1405  rdpTransport* transport = NULL;
1406  rdpSettings* settings = freerdp_settings_new(0);
1407  rdpContext* context = calloc(1, sizeof(rdpContext));
1408 
1409  if (!settings)
1410  goto fail;
1411  if (!freerdp_settings_set_bool(settings, FreeRDP_TransportDumpReplay, TRUE))
1412  goto fail;
1413 
1414  if (!context)
1415  goto fail;
1416  context->settings = settings;
1417  transport = transport_new(context);
1418  if (!transport)
1419  goto fail;
1420  return mcs_new(transport);
1421 
1422 fail:
1423  transport_free(transport);
1424  free(context);
1425  freerdp_settings_free(settings);
1426 
1427  return NULL;
1428 }
1429 
1430 BOOL freerdp_is_valid_mcs_create_request(const BYTE* data, size_t size)
1431 {
1432 
1433  wStream sbuffer = { 0 };
1434  wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1435 
1436  WINPR_ASSERT(data || (size == 0));
1437  WINPR_ASSERT(s);
1438 
1439  rdpMcs* mcs = test_mcs_new();
1440  WINPR_ASSERT(mcs);
1441 
1442  BOOL result = mcs_recv_connect_initial(mcs, s);
1443  test_mcs_free(mcs);
1444  return result;
1445 }
1446 
1447 BOOL freerdp_is_valid_mcs_create_response(const BYTE* data, size_t size)
1448 {
1449 
1450  wStream sbuffer = { 0 };
1451  wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1452 
1453  WINPR_ASSERT(data || (size == 0));
1454  WINPR_ASSERT(s);
1455 
1456  rdpMcs* mcs = test_mcs_new();
1457  WINPR_ASSERT(mcs);
1458 
1459  BOOL result = mcs_recv_connect_response(mcs, s);
1460  test_mcs_free(mcs);
1461  return result;
1462 }
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 rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
FREERDP_API void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
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.