diff --git a/include/freerdp/utils/smartcard_call.h b/include/freerdp/utils/smartcard_call.h index 2589cadab..166b737b5 100644 --- a/include/freerdp/utils/smartcard_call.h +++ b/include/freerdp/utils/smartcard_call.h @@ -44,6 +44,13 @@ extern "C" WINPR_ATTR_NODISCARD FREERDP_API scard_call_context* smartcard_call_context_new(const rdpSettings* settings); + /** @brief send a stop signal (or reset it if \b reset is \b TRUE) to a \ref scard_call_context + * + * @param ctx The context to send the signal to. Must not be \b nullptr + * @param reset Set or reset the signal + * + * @return \b TRUE for success, \b FALSE otherwise. + */ FREERDP_API BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset); WINPR_ATTR_NODISCARD diff --git a/libfreerdp/utils/smartcard_call.c b/libfreerdp/utils/smartcard_call.c index b1c3ae7af..7c1d966b6 100644 --- a/libfreerdp/utils/smartcard_call.c +++ b/libfreerdp/utils/smartcard_call.c @@ -2051,7 +2051,8 @@ BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hConte BOOL smartcard_call_cancel_all_context(scard_call_context* ctx) { - WINPR_ASSERT(ctx); + if (!ctx) + return FALSE; smartcard_call_context_signal_stop(ctx, FALSE); HashTable_Clear(ctx->rgSCardContextList); @@ -2094,6 +2095,7 @@ BOOL smartcard_call_is_configured(scard_call_context* ctx) BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset) { WINPR_ASSERT(ctx); + if (!ctx->stopEvent) return TRUE; diff --git a/server/proxy/channels/pf_channel_smartcard.c b/server/proxy/channels/pf_channel_smartcard.c index 1b9a60a62..56a290c80 100644 --- a/server/proxy/channels/pf_channel_smartcard.c +++ b/server/proxy/channels/pf_channel_smartcard.c @@ -271,17 +271,22 @@ BOOL pf_channel_smartcard_server_handle(WINPR_ATTR_UNUSED pServerContext* ps, static void channel_stop_and_wait(pf_channel_client_context* scard, BOOL reset) { WINPR_ASSERT(scard); - smartcard_call_context_signal_stop(scard->callctx, FALSE); + if (scard->callctx) + smartcard_call_context_signal_stop(scard->callctx, FALSE); - while (ArrayList_Count(scard->workObjects) > 0) + if (scard->workObjects) { - PTP_WORK work = ArrayList_GetItem(scard->workObjects, 0); - if (!work) - continue; - WaitForThreadpoolWorkCallbacks(work, TRUE); + while (ArrayList_Count(scard->workObjects) > 0) + { + PTP_WORK work = ArrayList_GetItem(scard->workObjects, 0); + if (!work) + continue; + WaitForThreadpoolWorkCallbacks(work, TRUE); + } } - smartcard_call_context_signal_stop(scard->callctx, reset); + if (scard->callctx) + smartcard_call_context_signal_stop(scard->callctx, reset); } static void pf_channel_scard_client_context_free(InterceptContextMapEntry* base) @@ -341,13 +346,10 @@ static void work_object_free(void* arg) BOOL pf_channel_smartcard_client_new(pClientContext* pc) { - pf_channel_client_context* scard = nullptr; - wObject* obj = nullptr; - WINPR_ASSERT(pc); WINPR_ASSERT(pc->interceptContextMap); - scard = calloc(1, sizeof(pf_channel_client_context)); + pf_channel_client_context* scard = calloc(1, sizeof(pf_channel_client_context)); if (!scard) return FALSE; scard->base.free = pf_channel_scard_client_context_free; @@ -358,11 +360,18 @@ BOOL pf_channel_smartcard_client_new(pClientContext* pc) scard->workObjects = ArrayList_New(TRUE); if (!scard->workObjects) goto fail; - obj = ArrayList_Object(scard->workObjects); - WINPR_ASSERT(obj); - obj->fnObjectFree = work_object_free; - return HashTable_Insert(pc->interceptContextMap, SCARD_SVC_CHANNEL_NAME, scard); + { + wObject* obj = ArrayList_Object(scard->workObjects); + WINPR_ASSERT(obj); + obj->fnObjectFree = work_object_free; + } + + if (!HashTable_Insert(pc->interceptContextMap, SCARD_SVC_CHANNEL_NAME, scard)) + goto fail; + + // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of rdpdr + return TRUE; fail: pf_channel_scard_client_context_free(&scard->base); return FALSE;