FreeRDP
Loading...
Searching...
No Matches
channels/client/addin.c
1
22#include <freerdp/config.h>
23
24#include <winpr/crt.h>
25#include <winpr/assert.h>
26#include <winpr/path.h>
27#include <winpr/string.h>
28#include <winpr/file.h>
29#include <winpr/synch.h>
30#include <winpr/library.h>
31#include <winpr/collections.h>
32
33#include <freerdp/freerdp.h>
34#include <freerdp/addin.h>
35#include <freerdp/build-config.h>
36#include <freerdp/client/channels.h>
37
38#include "tables.h"
39
40#include "addin.h"
41
42#include <freerdp/channels/log.h>
43#define TAG CHANNELS_TAG("addin")
44
45extern const STATIC_ENTRY_TABLE CLIENT_STATIC_ENTRY_TABLES[];
46
47static void* freerdp_channels_find_static_entry_in_table(const STATIC_ENTRY_TABLE* table,
48 const char* identifier)
49{
50 size_t index = 0;
51 const STATIC_ENTRY* pEntry = &table->table.cse[index++];
52
53 while (pEntry->entry != NULL)
54 {
55 static_entry_fn_t fkt = pEntry->entry;
56 if (strcmp(pEntry->name, identifier) == 0)
57 return WINPR_FUNC_PTR_CAST(fkt, void*);
58
59 pEntry = &table->table.cse[index++];
60 }
61
62 return NULL;
63}
64
65void* freerdp_channels_client_find_static_entry(const char* name, const char* identifier)
66{
67 size_t index = 0;
68 const STATIC_ENTRY_TABLE* pEntry = &CLIENT_STATIC_ENTRY_TABLES[index++];
69
70 while (pEntry->table.cse != NULL)
71 {
72 if (strcmp(pEntry->name, name) == 0)
73 {
74 return freerdp_channels_find_static_entry_in_table(pEntry, identifier);
75 }
76
77 pEntry = &CLIENT_STATIC_ENTRY_TABLES[index++];
78 }
79
80 return NULL;
81}
82
83extern const STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[];
84
85static FREERDP_ADDIN** freerdp_channels_list_client_static_addins(
86 WINPR_ATTR_UNUSED LPCSTR pszName, WINPR_ATTR_UNUSED LPCSTR pszSubsystem,
87 WINPR_ATTR_UNUSED LPCSTR pszType, WINPR_ATTR_UNUSED DWORD dwFlags)
88{
89 DWORD nAddins = 0;
90 FREERDP_ADDIN** ppAddins = NULL;
91 const STATIC_SUBSYSTEM_ENTRY* subsystems = NULL;
92 nAddins = 0;
93 ppAddins = (FREERDP_ADDIN**)calloc(128, sizeof(FREERDP_ADDIN*));
94
95 if (!ppAddins)
96 {
97 WLog_ERR(TAG, "calloc failed!");
98 return NULL;
99 }
100
101 ppAddins[nAddins] = NULL;
102
103 for (size_t i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++)
104 {
105 FREERDP_ADDIN* pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN));
106 const STATIC_ADDIN_TABLE* table = &CLIENT_STATIC_ADDIN_TABLE[i];
107 if (!pAddin)
108 {
109 WLog_ERR(TAG, "calloc failed!");
110 goto error_out;
111 }
112
113 (void)sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
114 pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
115 pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
116 pAddin->dwFlags |= FREERDP_ADDIN_NAME;
117 ppAddins[nAddins++] = pAddin;
118 subsystems = table->table;
119
120 for (size_t j = 0; subsystems[j].name != NULL; j++)
121 {
122 pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN));
123
124 if (!pAddin)
125 {
126 WLog_ERR(TAG, "calloc failed!");
127 goto error_out;
128 }
129
130 (void)sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
131 (void)sprintf_s(pAddin->cSubsystem, ARRAYSIZE(pAddin->cSubsystem), "%s",
132 subsystems[j].name);
133 pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
134 pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
135 pAddin->dwFlags |= FREERDP_ADDIN_NAME;
136 pAddin->dwFlags |= FREERDP_ADDIN_SUBSYSTEM;
137 ppAddins[nAddins++] = pAddin;
138 }
139 }
140
141 return ppAddins;
142error_out:
143 freerdp_channels_addin_list_free(ppAddins);
144 return NULL;
145}
146
147static HANDLE FindFirstFileUTF8(LPCSTR pszSearchPath, WIN32_FIND_DATAW* FindData)
148{
149 HANDLE hdl = INVALID_HANDLE_VALUE;
150 if (!pszSearchPath)
151 return hdl;
152 WCHAR* wpath = ConvertUtf8ToWCharAlloc(pszSearchPath, NULL);
153 if (!wpath)
154 return hdl;
155
156 hdl = FindFirstFileW(wpath, FindData);
157 free(wpath);
158
159 return hdl;
160}
161
162static FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPCSTR pszName, LPCSTR pszSubsystem,
163 LPCSTR pszType,
164 WINPR_ATTR_UNUSED DWORD dwFlags)
165{
166 int nDashes = 0;
167 HANDLE hFind = NULL;
168 DWORD nAddins = 0;
169 LPSTR pszPattern = NULL;
170 size_t cchPattern = 0;
171 LPCSTR pszAddinPath = FREERDP_ADDIN_PATH;
172 LPCSTR pszInstallPrefix = FREERDP_INSTALL_PREFIX;
173 LPCSTR pszExtension = NULL;
174 LPSTR pszSearchPath = NULL;
175 size_t cchSearchPath = 0;
176 size_t cchAddinPath = 0;
177 size_t cchInstallPrefix = 0;
178 FREERDP_ADDIN** ppAddins = NULL;
179 WIN32_FIND_DATAW FindData = { 0 };
180 cchAddinPath = strnlen(pszAddinPath, sizeof(FREERDP_ADDIN_PATH));
181 cchInstallPrefix = strnlen(pszInstallPrefix, sizeof(FREERDP_INSTALL_PREFIX));
182 pszExtension = PathGetSharedLibraryExtensionA(0);
183 cchPattern = 128 + strnlen(pszExtension, MAX_PATH) + 2;
184 pszPattern = (LPSTR)malloc(cchPattern + 1);
185
186 if (!pszPattern)
187 {
188 WLog_ERR(TAG, "malloc failed!");
189 return NULL;
190 }
191
192 if (pszName && pszSubsystem && pszType)
193 {
194 (void)sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client-%s-%s.%s",
195 pszName, pszSubsystem, pszType, pszExtension);
196 }
197 else if (pszName && pszType)
198 {
199 (void)sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client-?-%s.%s",
200 pszName, pszType, pszExtension);
201 }
202 else if (pszName)
203 {
204 (void)sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client*.%s",
205 pszName, pszExtension);
206 }
207 else
208 {
209 (void)sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "?-client*.%s",
210 pszExtension);
211 }
212
213 cchPattern = strnlen(pszPattern, cchPattern);
214 cchSearchPath = cchInstallPrefix + cchAddinPath + cchPattern + 3;
215 pszSearchPath = (LPSTR)calloc(cchSearchPath + 1, sizeof(char));
216
217 if (!pszSearchPath)
218 {
219 WLog_ERR(TAG, "malloc failed!");
220 free(pszPattern);
221 return NULL;
222 }
223
224 CopyMemory(pszSearchPath, pszInstallPrefix, cchInstallPrefix);
225 pszSearchPath[cchInstallPrefix] = '\0';
226 const HRESULT hr1 = NativePathCchAppendA(pszSearchPath, cchSearchPath + 1, pszAddinPath);
227 const HRESULT hr2 = NativePathCchAppendA(pszSearchPath, cchSearchPath + 1, pszPattern);
228 free(pszPattern);
229
230 if (FAILED(hr1) || FAILED(hr2))
231 {
232 free(pszSearchPath);
233 return NULL;
234 }
235
236 hFind = FindFirstFileUTF8(pszSearchPath, &FindData);
237
238 free(pszSearchPath);
239 nAddins = 0;
240 ppAddins = (FREERDP_ADDIN**)calloc(128, sizeof(FREERDP_ADDIN*));
241
242 if (!ppAddins)
243 {
244 FindClose(hFind);
245 WLog_ERR(TAG, "calloc failed!");
246 return NULL;
247 }
248
249 if (hFind == INVALID_HANDLE_VALUE)
250 return ppAddins;
251
252 do
253 {
254 char* cFileName = NULL;
255 BOOL used = FALSE;
256 FREERDP_ADDIN* pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN));
257
258 if (!pAddin)
259 {
260 WLog_ERR(TAG, "calloc failed!");
261 goto error_out;
262 }
263
264 cFileName =
265 ConvertWCharNToUtf8Alloc(FindData.cFileName, ARRAYSIZE(FindData.cFileName), NULL);
266 if (!cFileName)
267 goto skip;
268
269 nDashes = 0;
270 for (size_t index = 0; cFileName[index]; index++)
271 nDashes += (cFileName[index] == '-') ? 1 : 0;
272
273 if (nDashes == 1)
274 {
275 size_t len = 0;
276 char* p[2] = { 0 };
277 /* <name>-client.<extension> */
278 p[0] = cFileName;
279 p[1] = strchr(p[0], '-');
280 if (!p[1])
281 goto skip;
282 p[1] += 1;
283
284 len = (size_t)(p[1] - p[0]);
285 if (len < 1)
286 {
287 WLog_WARN(TAG, "Skipping file '%s', invalid format", cFileName);
288 goto skip;
289 }
290 strncpy(pAddin->cName, p[0], MIN(ARRAYSIZE(pAddin->cName), len - 1));
291
292 pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
293 pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
294 pAddin->dwFlags |= FREERDP_ADDIN_NAME;
295 ppAddins[nAddins++] = pAddin;
296
297 used = TRUE;
298 }
299 else if (nDashes == 2)
300 {
301 size_t len = 0;
302 char* p[4] = { 0 };
303 /* <name>-client-<subsystem>.<extension> */
304 p[0] = cFileName;
305 p[1] = strchr(p[0], '-');
306 if (!p[1])
307 goto skip;
308 p[1] += 1;
309 p[2] = strchr(p[1], '-');
310 if (!p[2])
311 goto skip;
312 p[2] += 1;
313 p[3] = strchr(p[2], '.');
314 if (!p[3])
315 goto skip;
316 p[3] += 1;
317
318 len = (size_t)(p[1] - p[0]);
319 if (len < 1)
320 {
321 WLog_WARN(TAG, "Skipping file '%s', invalid format", cFileName);
322 goto skip;
323 }
324 strncpy(pAddin->cName, p[0], MIN(ARRAYSIZE(pAddin->cName), len - 1));
325
326 len = (size_t)(p[3] - p[2]);
327 if (len < 1)
328 {
329 WLog_WARN(TAG, "Skipping file '%s', invalid format", cFileName);
330 goto skip;
331 }
332 strncpy(pAddin->cSubsystem, p[2], MIN(ARRAYSIZE(pAddin->cSubsystem), len - 1));
333
334 pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
335 pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
336 pAddin->dwFlags |= FREERDP_ADDIN_NAME;
337 pAddin->dwFlags |= FREERDP_ADDIN_SUBSYSTEM;
338 ppAddins[nAddins++] = pAddin;
339
340 used = TRUE;
341 }
342 else if (nDashes == 3)
343 {
344 size_t len = 0;
345 char* p[5] = { 0 };
346 /* <name>-client-<subsystem>-<type>.<extension> */
347 p[0] = cFileName;
348 p[1] = strchr(p[0], '-');
349 if (!p[1])
350 goto skip;
351 p[1] += 1;
352 p[2] = strchr(p[1], '-');
353 if (!p[2])
354 goto skip;
355 p[2] += 1;
356 p[3] = strchr(p[2], '-');
357 if (!p[3])
358 goto skip;
359 p[3] += 1;
360 p[4] = strchr(p[3], '.');
361 if (!p[4])
362 goto skip;
363 p[4] += 1;
364
365 len = (size_t)(p[1] - p[0]);
366 if (len < 1)
367 {
368 WLog_WARN(TAG, "Skipping file '%s', invalid format", cFileName);
369 goto skip;
370 }
371 strncpy(pAddin->cName, p[0], MIN(ARRAYSIZE(pAddin->cName), len - 1));
372
373 len = (size_t)(p[3] - p[2]);
374 if (len < 1)
375 {
376 WLog_WARN(TAG, "Skipping file '%s', invalid format", cFileName);
377 goto skip;
378 }
379 strncpy(pAddin->cSubsystem, p[2], MIN(ARRAYSIZE(pAddin->cSubsystem), len - 1));
380
381 len = (size_t)(p[4] - p[3]);
382 if (len < 1)
383 {
384 WLog_WARN(TAG, "Skipping file '%s', invalid format", cFileName);
385 goto skip;
386 }
387 strncpy(pAddin->cType, p[3], MIN(ARRAYSIZE(pAddin->cType), len - 1));
388
389 pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
390 pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
391 pAddin->dwFlags |= FREERDP_ADDIN_NAME;
392 pAddin->dwFlags |= FREERDP_ADDIN_SUBSYSTEM;
393 pAddin->dwFlags |= FREERDP_ADDIN_TYPE;
394 ppAddins[nAddins++] = pAddin;
395
396 used = TRUE;
397 }
398
399 skip:
400 free(cFileName);
401 if (!used)
402 free(pAddin);
403
404 } while (FindNextFileW(hFind, &FindData));
405
406 FindClose(hFind);
407 ppAddins[nAddins] = NULL;
408 return ppAddins;
409error_out:
410 FindClose(hFind);
411 freerdp_channels_addin_list_free(ppAddins);
412 return NULL;
413}
414
415FREERDP_ADDIN** freerdp_channels_list_addins(LPCSTR pszName, LPCSTR pszSubsystem, LPCSTR pszType,
416 DWORD dwFlags)
417{
418 if (dwFlags & FREERDP_ADDIN_STATIC)
419 return freerdp_channels_list_client_static_addins(pszName, pszSubsystem, pszType, dwFlags);
420 else if (dwFlags & FREERDP_ADDIN_DYNAMIC)
421 return freerdp_channels_list_dynamic_addins(pszName, pszSubsystem, pszType, dwFlags);
422
423 return NULL;
424}
425
426void freerdp_channels_addin_list_free(FREERDP_ADDIN** ppAddins)
427{
428 if (!ppAddins)
429 return;
430
431 for (size_t index = 0; ppAddins[index] != NULL; index++)
432 free(ppAddins[index]);
433
434 free((void*)ppAddins);
435}
436
437extern const STATIC_ENTRY CLIENT_VirtualChannelEntryEx_TABLE[];
438
439static BOOL freerdp_channels_is_virtual_channel_entry_ex(LPCSTR pszName)
440{
441 for (size_t i = 0; CLIENT_VirtualChannelEntryEx_TABLE[i].name != NULL; i++)
442 {
443 const STATIC_ENTRY* entry = &CLIENT_VirtualChannelEntryEx_TABLE[i];
444
445 if (!strncmp(entry->name, pszName, MAX_PATH))
446 return TRUE;
447 }
448
449 return FALSE;
450}
451
452PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPCSTR pszSubsystem,
453 LPCSTR pszType, DWORD dwFlags)
454{
455 const STATIC_ADDIN_TABLE* table = CLIENT_STATIC_ADDIN_TABLE;
456 const char* type = NULL;
457
458 if (!pszName)
459 return NULL;
460
461 if (dwFlags & FREERDP_ADDIN_CHANNEL_DYNAMIC)
462 type = "DVCPluginEntry";
463 else if (dwFlags & FREERDP_ADDIN_CHANNEL_DEVICE)
464 type = "DeviceServiceEntry";
465 else if (dwFlags & FREERDP_ADDIN_CHANNEL_STATIC)
466 {
467 if (dwFlags & FREERDP_ADDIN_CHANNEL_ENTRYEX)
468 type = "VirtualChannelEntryEx";
469 else
470 type = "VirtualChannelEntry";
471 }
472
473 for (; table->name != NULL; table++)
474 {
475 if (strncmp(table->name, pszName, MAX_PATH) == 0)
476 {
477 if (type && (strncmp(table->type, type, MAX_PATH) != 0))
478 continue;
479
480 if (pszSubsystem != NULL)
481 {
482 const STATIC_SUBSYSTEM_ENTRY* subsystems = table->table;
483
484 for (; subsystems->name != NULL; subsystems++)
485 {
486 /* If the pszSubsystem is an empty string use the default backend. */
487 if ((strnlen(pszSubsystem, 1) ==
488 0) || /* we only want to know if strnlen is > 0 */
489 (strncmp(subsystems->name, pszSubsystem, MAX_PATH) == 0))
490 {
491 static_subsystem_entry_fn_t fkt = subsystems->entry;
492
493 if (pszType)
494 {
495 if (strncmp(subsystems->type, pszType, MAX_PATH) == 0)
496 return WINPR_FUNC_PTR_CAST(fkt, PVIRTUALCHANNELENTRY);
497 }
498 else
499 return WINPR_FUNC_PTR_CAST(fkt, PVIRTUALCHANNELENTRY);
500 }
501 }
502 }
503 else
504 {
505 if (dwFlags & FREERDP_ADDIN_CHANNEL_ENTRYEX)
506 {
507 if (!freerdp_channels_is_virtual_channel_entry_ex(pszName))
508 return NULL;
509 }
510
511 return table->entry.csevc;
512 }
513 }
514 }
515
516 return NULL;
517}
518
519typedef struct
520{
521 wMessageQueue* queue;
522 wStream* data_in;
523 HANDLE thread;
524 char* channel_name;
525 rdpContext* ctx;
526 LPVOID userdata;
527 MsgHandler msg_handler;
528} msg_proc_internals;
529
530static DWORD WINAPI channel_client_thread_proc(LPVOID userdata)
531{
532 UINT error = CHANNEL_RC_OK;
533 wStream* data = NULL;
534 wMessage message = { 0 };
535 msg_proc_internals* internals = userdata;
536
537 WINPR_ASSERT(internals);
538
539 while (1)
540 {
541 if (!MessageQueue_Wait(internals->queue))
542 {
543 WLog_ERR(TAG, "MessageQueue_Wait failed!");
544 error = ERROR_INTERNAL_ERROR;
545 break;
546 }
547 if (!MessageQueue_Peek(internals->queue, &message, TRUE))
548 {
549 WLog_ERR(TAG, "MessageQueue_Peek failed!");
550 error = ERROR_INTERNAL_ERROR;
551 break;
552 }
553
554 if (message.id == WMQ_QUIT)
555 break;
556
557 if (message.id == 0)
558 {
559 data = (wStream*)message.wParam;
560
561 if ((error = internals->msg_handler(internals->userdata, data)))
562 {
563 WLog_ERR(TAG, "msg_handler failed with error %" PRIu32 "!", error);
564 break;
565 }
566 }
567 }
568 if (error && internals->ctx)
569 {
570 char msg[128];
571 (void)_snprintf(msg, 127,
572 "%s_virtual_channel_client_thread reported an"
573 " error",
574 internals->channel_name);
575 setChannelError(internals->ctx, error, msg);
576 }
577 ExitThread(error);
578 return error;
579}
580
581static void free_msg(void* obj)
582{
583 wMessage* msg = (wMessage*)obj;
584
585 if (msg && (msg->id == 0))
586 {
587 wStream* s = (wStream*)msg->wParam;
588 Stream_Free(s, TRUE);
589 }
590}
591
592static void channel_client_handler_free(msg_proc_internals* internals)
593{
594 if (!internals)
595 return;
596
597 if (internals->thread)
598 (void)CloseHandle(internals->thread);
599 MessageQueue_Free(internals->queue);
600 Stream_Free(internals->data_in, TRUE);
601 free(internals->channel_name);
602 free(internals);
603}
604
605/* Create message queue and thread or not, depending on settings */
606void* channel_client_create_handler(rdpContext* ctx, LPVOID userdata, MsgHandler msg_handler,
607 const char* channel_name)
608{
609 msg_proc_internals* internals = calloc(1, sizeof(msg_proc_internals));
610 if (!internals)
611 {
612 WLog_ERR(TAG, "calloc failed!");
613 return NULL;
614 }
615 internals->msg_handler = msg_handler;
616 internals->userdata = userdata;
617 if (channel_name)
618 {
619 internals->channel_name = _strdup(channel_name);
620 if (!internals->channel_name)
621 goto fail;
622 }
623 WINPR_ASSERT(ctx);
624 WINPR_ASSERT(ctx->settings);
625 internals->ctx = ctx;
626 if ((freerdp_settings_get_uint32(ctx->settings, FreeRDP_ThreadingFlags) &
627 THREADING_FLAGS_DISABLE_THREADS) == 0)
628 {
629 wObject obj = { 0 };
630 obj.fnObjectFree = free_msg;
631 internals->queue = MessageQueue_New(&obj);
632 if (!internals->queue)
633 {
634 WLog_ERR(TAG, "MessageQueue_New failed!");
635 goto fail;
636 }
637
638 if (!(internals->thread =
639 CreateThread(NULL, 0, channel_client_thread_proc, (void*)internals, 0, NULL)))
640 {
641 WLog_ERR(TAG, "CreateThread failed!");
642 goto fail;
643 }
644 }
645 return internals;
646
647fail:
648 channel_client_handler_free(internals);
649 return NULL;
650}
651/* post a message in the queue or directly call the processing handler */
652UINT channel_client_post_message(void* MsgsHandle, LPVOID pData, UINT32 dataLength,
653 UINT32 totalLength, UINT32 dataFlags)
654{
655 msg_proc_internals* internals = MsgsHandle;
656 wStream* data_in = NULL;
657
658 if (!internals)
659 {
660 /* TODO: return some error here */
661 return CHANNEL_RC_OK;
662 }
663
664 if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
665 {
666 return CHANNEL_RC_OK;
667 }
668
669 if (dataFlags & CHANNEL_FLAG_FIRST)
670 {
671 if (internals->data_in)
672 {
673 if (!Stream_EnsureCapacity(internals->data_in, totalLength))
674 return CHANNEL_RC_NO_MEMORY;
675 }
676 else
677 internals->data_in = Stream_New(NULL, totalLength);
678 }
679
680 if (!(data_in = internals->data_in))
681 {
682 WLog_ERR(TAG, "Stream_New failed!");
683 return CHANNEL_RC_NO_MEMORY;
684 }
685
686 if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
687 {
688 Stream_Free(internals->data_in, TRUE);
689 internals->data_in = NULL;
690 return CHANNEL_RC_NO_MEMORY;
691 }
692
693 Stream_Write(data_in, pData, dataLength);
694
695 if (dataFlags & CHANNEL_FLAG_LAST)
696 {
697 if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
698 {
699 char msg[128];
700 (void)_snprintf(msg, 127, "%s_plugin_process_received: read error",
701 internals->channel_name);
702 WLog_ERR(TAG, msg);
703 return ERROR_INTERNAL_ERROR;
704 }
705
706 internals->data_in = NULL;
707 Stream_SealLength(data_in);
708 Stream_SetPosition(data_in, 0);
709
710 if ((freerdp_settings_get_uint32(internals->ctx->settings, FreeRDP_ThreadingFlags) &
711 THREADING_FLAGS_DISABLE_THREADS) != 0)
712 {
713 UINT error = CHANNEL_RC_OK;
714 if ((error = internals->msg_handler(internals->userdata, data_in)))
715 {
716 WLog_ERR(TAG,
717 "msg_handler failed with error"
718 " %" PRIu32 "!",
719 error);
720 return ERROR_INTERNAL_ERROR;
721 }
722 }
723 else if (!MessageQueue_Post(internals->queue, NULL, 0, (void*)data_in, NULL))
724 {
725 WLog_ERR(TAG, "MessageQueue_Post failed!");
726 return ERROR_INTERNAL_ERROR;
727 }
728 }
729 return CHANNEL_RC_OK;
730}
731/* Tear down queue and thread */
732UINT channel_client_quit_handler(void* MsgsHandle)
733{
734 msg_proc_internals* internals = MsgsHandle;
735 UINT rc = 0;
736 if (!internals)
737 {
738 /* TODO: return some error here */
739 return CHANNEL_RC_OK;
740 }
741
742 WINPR_ASSERT(internals->ctx);
743 WINPR_ASSERT(internals->ctx->settings);
744
745 if ((freerdp_settings_get_uint32(internals->ctx->settings, FreeRDP_ThreadingFlags) &
746 THREADING_FLAGS_DISABLE_THREADS) == 0)
747 {
748 if (internals->queue && internals->thread)
749 {
750 if (MessageQueue_PostQuit(internals->queue, 0) &&
751 (WaitForSingleObject(internals->thread, INFINITE) == WAIT_FAILED))
752 {
753 rc = GetLastError();
754 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc);
755 return rc;
756 }
757 }
758 }
759
760 channel_client_handler_free(internals);
761 return CHANNEL_RC_OK;
762}
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
Definition tables.h:84
Definition tables.h:32
Definition tables.h:91
This struct contains function pointer to initialize/free objects.
Definition collections.h:57