From: Martin Haimberger Date: Wed, 15 Jul 2015 07:50:35 +0000 (-0700) Subject: introduced channel error reporting system X-Git-Tag: 2.0.0-beta1+android10~455^2~11 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b8c110d19b75f17320ef9d08b411d5d10f1adf54;p=platform%2Fupstream%2Ffreerdp.git introduced channel error reporting system The rdpContext gets an event which will get set if an error occoured in a channel. If a thread or a void callback has to report an error it will get signaled by this system. --- diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c index 0f4b042..93a5a0d 100644 --- a/channels/audin/client/alsa/audin_alsa.c +++ b/channels/audin/client/alsa/audin_alsa.c @@ -65,6 +65,8 @@ typedef struct _AudinALSADevice AudinReceive receive; void* user_data; + + rdpContext* rdpcontext; } AudinALSADevice; static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_handle) @@ -148,9 +150,13 @@ static WIN32ERROR audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, in { if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM) { - alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context, + if (!alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context, alsa->buffer, alsa->buffer_frames * tbytes_per_frame, - alsa->target_channels, alsa->block_size); + alsa->target_channels, alsa->block_size)) + { + ret = ERROR_INTERNAL_ERROR; + break; + } encoded_data = alsa->dsp_context->adpcm_buffer; encoded_size = alsa->dsp_context->adpcm_size; @@ -204,7 +210,8 @@ static void* audin_alsa_thread_func(void* arg) if (!buffer) { WLog_ERR(TAG, "calloc failed!"); - //TODO: signal error to freerdp + if (alsa->rdpcontext) + setChannelError(alsa->rdpcontext, CHANNEL_RC_NO_MEMORY, "calloc failed!"); ExitThread((DWORD)CHANNEL_RC_NO_MEMORY); return NULL; } @@ -255,6 +262,8 @@ static void* audin_alsa_thread_func(void* arg) snd_pcm_close(capture_handle); DEBUG_DVC("out"); + if (error && alsa->rdpcontext) + setChannelError(alsa->rdpcontext, error, "audin_alsa_thread_func reported an error"); ExitThread((DWORD)error); return NULL; @@ -363,7 +372,6 @@ static WIN32ERROR audin_alsa_open(IAudinDevice* device, AudinReceive receive, vo WLog_ERR(TAG, "CreateEvent failed!"); goto error_out; } - // TODO: add mechanism that threads can signal failure if (!(alsa->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL))) { @@ -469,6 +477,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POIN alsa->iface.SetFormat = audin_alsa_set_format; alsa->iface.Close = audin_alsa_close; alsa->iface.Free = audin_alsa_free; + alsa->rdpcontext = pEntryPoints->rdpcontext; args = pEntryPoints->args; diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 1284986..6aaa8c2 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -35,6 +35,7 @@ #include #include +#include #include "audin_main.h" #define MSG_SNDIN_VERSION 0x01 @@ -88,6 +89,8 @@ struct _AUDIN_PLUGIN /* Device interface */ IAudinDevice* device; + + rdpContext* rdpcontext; }; static WIN32ERROR audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) @@ -577,6 +580,7 @@ static WIN32ERROR audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name entryPoints.plugin = pPlugin; entryPoints.pRegisterAudinDevice = audin_register_device_plugin; entryPoints.args = args; + entryPoints.rdpcontext = ((AUDIN_PLUGIN*)pPlugin)->rdpcontext; if ((error = entry(&entryPoints))) { @@ -715,6 +719,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } args = pEntryPoints->GetPluginData(pEntryPoints); + audin->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context; if (error == CHANNEL_RC_OK) audin_process_addin_args((IWTSPlugin*) audin, args); diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index 841b1e4..4db37ce 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -39,6 +39,7 @@ #include #include +#include #include "audin_main.h" #include "opensl_io.h" @@ -66,6 +67,8 @@ typedef struct _AudinOpenSLESDevice HANDLE stopEvent; void* user_data; + + rdpContext* rdpcontext; } AudinOpenSLESDevice; static void* audin_opensles_thread_func(void* arg) @@ -79,6 +82,7 @@ static void* audin_opensles_thread_func(void* arg) AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) arg; const size_t raw_size = opensles->frames_per_packet * opensles->bytes_per_channel; int rc = CHANNEL_RC_OK; + WIN32ERROR error = CHANNEL_RC_OK; DEBUG_DVC("opensles=%p", opensles); @@ -92,7 +96,8 @@ static void* audin_opensles_thread_func(void* arg) if (!buffer.v) { WLog_ERR(TAG, "calloc failed!"); - //TODO: signal error to freerdp + if (opensles->rdpcontext) + setChannelError(opensles->rdpcontext, CHANNEL_RC_NO_MEMORY, "audin_opensles_thread_func reported an error"); ExitThread((DWORD)CHANNEL_RC_NO_MEMORY); return NULL; } @@ -114,17 +119,25 @@ static void* audin_opensles_thread_func(void* arg) assert(rc == raw_size); if (opensles->format == WAVE_FORMAT_ADPCM) { - opensles->dsp_context->encode_ms_adpcm(opensles->dsp_context, - buffer.b, rc, opensles->channels, opensles->block_size); + if (!opensles->dsp_context->encode_ms_adpcm(opensles->dsp_context, + buffer.b, rc, opensles->channels, opensles->block_size)) + { + error = ERROR_INTERNAL_ERROR; + break; + } encoded_data = opensles->dsp_context->adpcm_buffer; encoded_size = opensles->dsp_context->adpcm_size; } else if (opensles->format == WAVE_FORMAT_DVI_ADPCM) { - opensles->dsp_context->encode_ima_adpcm(opensles->dsp_context, + if (!opensles->dsp_context->encode_ima_adpcm(opensles->dsp_context, buffer.b, rc, - opensles->channels, opensles->block_size); + opensles->channels, opensles->block_size)) + { + error = ERROR_INTERNAL_ERROR; + break; + } encoded_data = opensles->dsp_context->adpcm_buffer; encoded_size = opensles->dsp_context->adpcm_size; @@ -135,8 +148,8 @@ static void* audin_opensles_thread_func(void* arg) encoded_size = rc; } - rc = opensles->receive(encoded_data, encoded_size, opensles->user_data); - if (rc) + error = opensles->receive(encoded_data, encoded_size, opensles->user_data); + if (error) break; } @@ -144,7 +157,10 @@ static void* audin_opensles_thread_func(void* arg) DEBUG_DVC("thread shutdown."); - ExitThread((DWORD)rc); + if (error && opensles->rdpcontext) + setChannelError(opensles->rdpcontext, error, "audin_opensles_thread_func reported an error"); + + ExitThread((DWORD)error); return NULL; } @@ -312,7 +328,6 @@ static WIN32ERROR audin_opensles_open(IAudinDevice* device, AudinReceive receive WLog_ERR(TAG, "CreateEvent failed!"); goto error_out; } - // TODO: add mechanism that threads can signal failure if (!(opensles->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_opensles_thread_func, opensles, 0, NULL))) @@ -441,6 +456,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry( opensles->iface.SetFormat = audin_opensles_set_format; opensles->iface.Close = audin_opensles_close; opensles->iface.Free = audin_opensles_free; + opensles->rdpcontext = pEntryPoints->rdpcontext; args = pEntryPoints->args; diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c index b45f7b7..b8b54b1 100644 --- a/channels/audin/client/oss/audin_oss.c +++ b/channels/audin/client/oss/audin_oss.c @@ -66,6 +66,8 @@ typedef struct _AudinOSSDevice { AudinReceive receive; void* user_data; + + rdpContext* rdpcontext; } AudinOSSDevice; #define OSS_LOG_ERR(_text, _error) \ @@ -156,13 +158,17 @@ static void *audin_oss_thread_func(void *arg) WIN32ERROR error; if (arg == NULL) + { + error = ERROR_INVALID_PARAMETER; goto err_out; + } if (oss->dev_unit != -1) snprintf(dev_name, (PATH_MAX - 1), "/dev/dsp%i", oss->dev_unit); WLog_INFO(TAG, "open: %s", dev_name); if ((pcm_handle = open(dev_name, O_RDONLY)) < 0) { OSS_LOG_ERR("sound dev open failed", errno); + error = (WIN32ERROR)errno; goto err_out; } #if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_INPUT flag. */ @@ -192,6 +198,7 @@ static void *audin_oss_thread_func(void *arg) buffer = (BYTE*)calloc(1, (buffer_size + sizeof(void*))); if (NULL == buffer) { OSS_LOG_ERR("malloc() fail", errno); + error = ERROR_NOT_ENOUGH_MEMORY; goto err_out; } @@ -208,14 +215,22 @@ static void *audin_oss_thread_func(void *arg) /* Process. */ switch (oss->format.wFormatTag) { case WAVE_FORMAT_ADPCM: - oss->dsp_context->encode_ms_adpcm(oss->dsp_context, - buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign); + if (!oss->dsp_context->encode_ms_adpcm(oss->dsp_context, + buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign)) + { + error = ERROR_INTERNAL_ERROR; + break; + } encoded_data = oss->dsp_context->adpcm_buffer; encoded_size = oss->dsp_context->adpcm_size; break; case WAVE_FORMAT_DVI_ADPCM: - oss->dsp_context->encode_ima_adpcm(oss->dsp_context, - buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign); + if (!oss->dsp_context->encode_ima_adpcm(oss->dsp_context, + buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign)) + { + error = ERROR_INTERNAL_ERROR; + break; + } encoded_data = oss->dsp_context->adpcm_buffer; encoded_size = oss->dsp_context->adpcm_size; break; @@ -233,6 +248,10 @@ static void *audin_oss_thread_func(void *arg) } err_out: + + if (error && oss->rdpcontext) + setChannelError(oss->rdpcontext, error, "audin_oss_thread_func reported an error"); + if (pcm_handle != -1) close(pcm_handle); free(buffer); @@ -253,7 +272,6 @@ static WIN32ERROR audin_oss_open(IAudinDevice *device, AudinReceive receive, voi WLog_ERR(TAG, "CreateEvent failed!"); return ERROR_INTERNAL_ERROR; } - // TODO: add mechanism that threads can signal failure if (!(oss->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL))) { @@ -374,6 +392,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POIN oss->iface.SetFormat = audin_oss_set_format; oss->iface.Close = audin_oss_close; oss->iface.Free = audin_oss_free; + oss->rdpcontext = pEntryPoints->rdpcontext; oss->dev_unit = -1; diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c index a5cd78a..c617b09 100644 --- a/channels/audin/client/pulse/audin_pulse.c +++ b/channels/audin/client/pulse/audin_pulse.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "audin_main.h" @@ -60,6 +61,8 @@ typedef struct _AudinPulseDevice AudinReceive receive; void* user_data; + + rdpContext* rdpcontext; } AudinPulseDevice; static void audin_pulse_context_state_callback(pa_context* context, void* userdata) @@ -280,12 +283,12 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length { int frames; int cframes; - BOOL ret; const void* data; const BYTE* src; int encoded_size; BYTE* encoded_data; AudinPulseDevice* pulse = (AudinPulseDevice*) userdata; + WIN32ERROR error = CHANNEL_RC_OK; /* There is a race condition here where we may receive this callback * before the buffer has been set up in the main code. It's probably @@ -316,9 +319,13 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length { if (pulse->format == 0x11) { - pulse->dsp_context->encode_ima_adpcm(pulse->dsp_context, + if (!pulse->dsp_context->encode_ima_adpcm(pulse->dsp_context, pulse->buffer, pulse->buffer_frames * pulse->bytes_per_frame, - pulse->sample_spec.channels, pulse->block_size); + pulse->sample_spec.channels, pulse->block_size)) + { + error = ERROR_INTERNAL_ERROR; + break; + } encoded_data = pulse->dsp_context->adpcm_buffer; encoded_size = pulse->dsp_context->adpcm_size; } @@ -331,9 +338,9 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length DEBUG_DVC("encoded %d [%d] to %d [%X]", pulse->buffer_frames, pulse->bytes_per_frame, encoded_size, pulse->format); - ret = pulse->receive(encoded_data, encoded_size, pulse->user_data); + error = pulse->receive(encoded_data, encoded_size, pulse->user_data); pulse->buffer_frames = 0; - if (!ret) + if (!error) break; } src += cframes * pulse->bytes_per_frame; @@ -341,6 +348,9 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length } pa_stream_drop(stream); + + if (error && pulse->rdpcontext) + setChannelError(pulse->rdpcontext, error, "audin_oss_thread_func reported an error"); } @@ -434,7 +444,7 @@ static WIN32ERROR audin_pulse_open(IAudinDevice* device, AudinReceive receive, v pulse->buffer = calloc(1, pulse->bytes_per_frame * pulse->frames_per_packet); if (!pulse->buffer) { WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_OK; + return CHANNEL_RC_NO_MEMORY; } pulse->buffer_frames = 0; DEBUG_DVC("connected"); @@ -506,6 +516,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POIN pulse->iface.SetFormat = audin_pulse_set_format; pulse->iface.Close = audin_pulse_close; pulse->iface.Free = audin_pulse_free; + pulse->rdpcontext = pEntryPoints->rdpcontext; args = pEntryPoints->args; diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c index c651feb..3e5f13b 100644 --- a/channels/audin/client/winmm/audin_winmm.c +++ b/channels/audin/client/winmm/audin_winmm.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "audin_main.h" @@ -51,6 +52,7 @@ typedef struct _AudinWinmmDevice UINT32 ppwfx_size; UINT32 cFormats; UINT32 frames_per_packet; + rdpContext* rdpcontext; } AudinWinmmDevice; static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance, @@ -58,6 +60,8 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance { AudinWinmmDevice* winmm = (AudinWinmmDevice*) dwInstance; PWAVEHDR pWaveHdr; + WIN32ERROR error = CHANNEL_RC_OK; + MMRESULT mmResult; switch(uMsg) { @@ -71,8 +75,11 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance if (pWaveHdr->dwBytesRecorded && !(WaitForSingleObject(winmm->stopEvent, 0) == WAIT_OBJECT_0)) { - winmm->receive(pWaveHdr->lpData, pWaveHdr->dwBytesRecorded, winmm->user_data); - waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR)); + if ((error = winmm->receive(pWaveHdr->lpData, pWaveHdr->dwBytesRecorded, winmm->user_data))) + break; + mmResult = waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR)); + if (mmResult != MMSYSERR_NOERROR) + error = ERROR_INTERNAL_ERROR; } } break; @@ -83,6 +90,8 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance default: break; } + if (error && winmm->rdpcontext) + setChannelError(winmm->rdpcontext, error, "waveInProc reported an error"); } static DWORD audin_winmm_thread_func(void* arg) @@ -97,6 +106,8 @@ static DWORD audin_winmm_thread_func(void* arg) if (MMSYSERR_NOERROR != waveInOpen(&winmm->hWaveIn, WAVE_MAPPER, winmm->pwfx_cur, (DWORD_PTR)waveInProc, (DWORD_PTR)winmm, CALLBACK_FUNCTION)) { + if (winmm->rdpcontext) + setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, "audin_winmm_thread_func reported an error"); return 0; } } @@ -113,10 +124,14 @@ static DWORD audin_winmm_thread_func(void* arg) if (MMSYSERR_NOERROR != waveInPrepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i]))) { DEBUG_DVC("waveInPrepareHeader failed."); + if (winmm->rdpcontext) + setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, "audin_winmm_thread_func reported an error"); } if (MMSYSERR_NOERROR != waveInAddBuffer(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i]))) { DEBUG_DVC("waveInAddBuffer failed."); + if (winmm->rdpcontext) + setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, "audin_winmm_thread_func reported an error"); } } waveInStart(winmm->hWaveIn); @@ -130,6 +145,8 @@ static DWORD audin_winmm_thread_func(void* arg) if (MMSYSERR_NOERROR != waveInUnprepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i]))) { DEBUG_DVC("waveInUnprepareHeader failed."); + if (winmm->rdpcontext) + setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, "audin_winmm_thread_func reported an error"); } free(waveHdr[i].lpData); } @@ -252,7 +269,7 @@ static WIN32ERROR audin_winmm_open(IAudinDevice* device, AudinReceive receive, v WLog_ERR(TAG, "CreateEvent failed!"); return ERROR_INTERNAL_ERROR; } - // TODO: add mechanism that threads can signal failure + if (!(winmm->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL))) { @@ -329,6 +346,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POIN winmm->iface.SetFormat = audin_winmm_set_format; winmm->iface.Close = audin_winmm_close; winmm->iface.Free = audin_winmm_free; + winmm->rdpcontext = pEntryPoints->rdpcontext; args = pEntryPoints->args; diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index 982f99a..d64ee75 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -497,6 +497,9 @@ out_capacity: out: WTSVirtualChannelClose(audin->audin_channel); audin->audin_channel = NULL; + if (error && audin->context.rdpcontext) + setChannelError(audin->context.rdpcontext, error, "audin_server_thread_func reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -534,7 +537,6 @@ static BOOL audin_server_open(audin_server_context* context) return FALSE; } - // TODO: implement signaling an error if (!(audin->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL))) { diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 42f1be8..6deb301 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -968,7 +968,11 @@ static WIN32ERROR cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cli Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - MessageQueue_Post(cliprdr->queue, NULL, 0, (void*) data_in, NULL); + if (!MessageQueue_Post(cliprdr->queue, NULL, 0, (void*) data_in, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } } return CHANNEL_RC_OK; } @@ -977,21 +981,20 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle, UINT LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { cliprdrPlugin* cliprdr; + WIN32ERROR error = CHANNEL_RC_OK; cliprdr = (cliprdrPlugin*) cliprdr_get_open_handle_data(openHandle); if (!cliprdr) { WLog_ERR(TAG, "cliprdr_virtual_channel_open_event: error no match"); - cliprdr->error = CHANNEL_RC_BAD_CHANNEL; return; } - cliprdr->error = CHANNEL_RC_OK; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - cliprdr->error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength, totalLength, dataFlags); + error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength, totalLength, dataFlags); break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -1001,7 +1004,10 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle, UINT case CHANNEL_EVENT_USER: break; } - //TODO report error + + if (error && cliprdr->context->rdpcontext) + setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_open_event reported an error"); + } static void* cliprdr_virtual_channel_client_thread(void* arg) @@ -1014,25 +1020,35 @@ static void* cliprdr_virtual_channel_client_thread(void* arg) while (1) { if (!MessageQueue_Wait(cliprdr->queue)) + { + WLog_ERR(TAG, "MessageQueue_Wait failed!"); + error = ERROR_INTERNAL_ERROR; break; + } - if (MessageQueue_Peek(cliprdr->queue, &message, TRUE)) + if (!MessageQueue_Peek(cliprdr->queue, &message, TRUE)) { - if (message.id == WMQ_QUIT) - break; + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; + break; + } + if (message.id == WMQ_QUIT) + break; - if (message.id == 0) + if (message.id == 0) + { + data = (wStream*) message.wParam; + if ((error = cliprdr_order_recv(cliprdr, data))) { - data = (wStream*) message.wParam; - if ((error = cliprdr_order_recv(cliprdr, data))) - { - WLog_ERR(TAG, "cliprdr_order_recv failed with error %lu!", error); - break; - } + WLog_ERR(TAG, "cliprdr_order_recv failed with error %lu!", error); + break; } } } + if (error && cliprdr->context->rdpcontext) + setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_client_thread reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -1115,37 +1131,36 @@ static WIN32ERROR cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprd static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { cliprdrPlugin* cliprdr; + WIN32ERROR error = CHANNEL_RC_OK; cliprdr = (cliprdrPlugin*) cliprdr_get_init_handle_data(pInitHandle); if (!cliprdr) { - WLog_ERR(TAG, "cliprdr_virtual_channel_init_event: error no match"); - cliprdr->error = CHANNEL_RC_BAD_CHANNEL; + WLog_ERR(TAG, "error no match"); return; } - cliprdr->error = CHANNEL_RC_OK; - switch (event) { case CHANNEL_EVENT_CONNECTED: - if ((cliprdr->error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength))) - WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %lu!", cliprdr->error); + if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength))) + WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %lu!", error); break; case CHANNEL_EVENT_DISCONNECTED: - if ((cliprdr->error = cliprdr_virtual_channel_event_disconnected(cliprdr))) - WLog_ERR(TAG, "cliprdr_virtual_channel_event_disconnected failed with error %lu!", cliprdr->error); + if ((error = cliprdr_virtual_channel_event_disconnected(cliprdr))) + WLog_ERR(TAG, "cliprdr_virtual_channel_event_disconnected failed with error %lu!", error); break; case CHANNEL_EVENT_TERMINATED: - if ((cliprdr->error = cliprdr_virtual_channel_event_terminated(cliprdr))) - WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %lu!", cliprdr->error); + if ((error = cliprdr_virtual_channel_event_terminated(cliprdr))) + WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %lu!", error); break; } - // to satisfy compiler - // TODO report error!!! + if (error && cliprdr->context->rdpcontext) + setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_init_event reported an error"); + return; } @@ -1205,6 +1220,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) *(pEntryPointsEx->ppInterface) = (void*) context; cliprdr->context = context; + context->rdpcontext = pEntryPointsEx->context; } cliprdr->log = WLog_Get("com.freerdp.channels.cliprdr.client"); diff --git a/channels/cliprdr/client/cliprdr_main.h b/channels/cliprdr/client/cliprdr_main.h index da78822..aea9589 100644 --- a/channels/cliprdr/client/cliprdr_main.h +++ b/channels/cliprdr/client/cliprdr_main.h @@ -50,7 +50,6 @@ struct cliprdr_plugin BOOL streamFileClipEnabled; BOOL fileClipNoFilePaths; BOOL canLockClipData; - WIN32ERROR error; }; typedef struct cliprdr_plugin cliprdrPlugin; diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c index 85b01a3..a2f7c42 100644 --- a/channels/cliprdr/server/cliprdr_main.c +++ b/channels/cliprdr/server/cliprdr_main.c @@ -1147,8 +1147,7 @@ static void* cliprdr_server_thread(void* arg) if ((error = cliprdr_server_init(context))) { WLog_ERR(TAG, "cliprdr_server_init failed with error %lu!", error); - ExitThread((DWORD)error); - return NULL; + goto out; } while (1) @@ -1156,9 +1155,7 @@ static void* cliprdr_server_thread(void* arg) status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(cliprdr->StopEvent, 0) == WAIT_OBJECT_0) - { break; - } if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0) { @@ -1169,6 +1166,10 @@ static void* cliprdr_server_thread(void* arg) } } } +out: + if (error && context->rdpcontext) + setChannelError(context->rdpcontext, error, "cliprdr_server_thread reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -1250,7 +1251,6 @@ static WIN32ERROR cliprdr_server_start(CliprdrServerContext* context) return ERROR_INTERNAL_ERROR; } - // TODO: add mechanism that threads can signal failure if (!(cliprdr->Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL))) { diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 213b4fa..cb55240 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -659,14 +659,10 @@ WIN32ERROR drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* da WLog_DBG(TAG, "write_data: ChannelId=%d size=%d", ChannelId, dataSize); - if (drdynvc->channel_error != CHANNEL_RC_OK) - return drdynvc->channel_error; - data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); if (!data_out) { - drdynvc->channel_error = CHANNEL_RC_NO_MEMORY; WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -716,7 +712,6 @@ WIN32ERROR drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* da data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); if (!data_out) { - drdynvc->channel_error = CHANNEL_RC_NO_MEMORY; WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -745,7 +740,6 @@ WIN32ERROR drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* da if (status != CHANNEL_RC_OK) { - drdynvc->channel_error = status; WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(status), status); return status; @@ -804,8 +798,6 @@ static WIN32ERROR drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int status = drdynvc_send_capability_response(drdynvc); - drdynvc->channel_error = status; - drdynvc->state = DRDYNVC_STATE_READY; return status; @@ -973,8 +965,6 @@ static WIN32ERROR drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, error = drdynvc_send(drdynvc, data_out); - drdynvc->channel_error = error; - if (error) WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(error), error); @@ -1155,7 +1145,11 @@ static WIN32ERROR drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drd Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL); + if (!MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } } return CHANNEL_RC_OK; } @@ -1164,22 +1158,21 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle, UINT LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { drdynvcPlugin* drdynvc; + WIN32ERROR error = CHANNEL_RC_OK; drdynvc = (drdynvcPlugin*) drdynvc_get_open_handle_data(openHandle); if (!drdynvc) { WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match"); - drdynvc->channel_error = CHANNEL_RC_BAD_CHANNEL; return; } - drdynvc->channel_error = CHANNEL_RC_OK; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - drdynvc->channel_error = drdynvc_virtual_channel_event_data_received(drdynvc, pData, dataLength, totalLength, dataFlags); - return; + if ((error = drdynvc_virtual_channel_event_data_received(drdynvc, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "drdynvc_virtual_channel_event_data_received failed with error %lu", error); break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -1189,7 +1182,9 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle, UINT case CHANNEL_EVENT_USER: break; } - //TODO signal error + if (error && drdynvc->rdpcontext) + setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_open_event reported an error"); + } static void* drdynvc_virtual_channel_client_thread(void* arg) @@ -1202,28 +1197,37 @@ static void* drdynvc_virtual_channel_client_thread(void* arg) while (1) { if (!MessageQueue_Wait(drdynvc->queue)) + { + WLog_ERR(TAG, "MessageQueue_Wait failed!"); + error = ERROR_INTERNAL_ERROR; break; + } - if (MessageQueue_Peek(drdynvc->queue, &message, TRUE)) + if (!MessageQueue_Peek(drdynvc->queue, &message, TRUE)) { - if (message.id == WMQ_QUIT) - break; + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; + break; + } - if (message.id == 0) + if (message.id == WMQ_QUIT) + break; + + if (message.id == 0) + { + data = (wStream*) message.wParam; + if ((error = drdynvc_order_recv(drdynvc, data))) { - data = (wStream*) message.wParam; - if ((error = drdynvc_order_recv(drdynvc, data))) - { - Stream_Free(data, TRUE); - WLog_ERR(TAG, "drdynvc_order_recv failed with error %lu!", error); - ExitThread((DWORD) error); - return NULL; - } Stream_Free(data, TRUE); + WLog_ERR(TAG, "drdynvc_order_recv failed with error %lu!", error); + break; } + Stream_Free(data, TRUE); } } + if (error && drdynvc->rdpcontext) + setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_client_thread reported an error"); ExitThread((DWORD) error); return NULL; } @@ -1252,7 +1256,6 @@ static WIN32ERROR drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc return error; } - drdynvc->queue = MessageQueue_New(NULL); if (!drdynvc->queue) { @@ -1268,7 +1271,6 @@ static WIN32ERROR drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc WLog_ERR(TAG, "dvcman_new failed!"); goto error; } - drdynvc->channel_error = CHANNEL_RC_OK; settings = (rdpSettings*) drdynvc->channelEntryPoints.pExtendedData; @@ -1294,6 +1296,8 @@ static WIN32ERROR drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc goto error; } + return CHANNEL_RC_OK; + error: drdynvc_remove_open_handle_data(drdynvc->OpenHandle); MessageQueue_Free(drdynvc->queue); @@ -1348,36 +1352,36 @@ static WIN32ERROR drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynv static void VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { drdynvcPlugin* drdynvc; + WIN32ERROR error = CHANNEL_RC_OK; drdynvc = (drdynvcPlugin*) drdynvc_get_init_handle_data(pInitHandle); if (!drdynvc) { WLog_ERR(TAG, "drdynvc_virtual_channel_init_event: error no match"); - drdynvc->channel_error = CHANNEL_RC_BAD_CHANNEL; return; } - drdynvc->channel_error = CHANNEL_RC_OK; - switch (event) { case CHANNEL_EVENT_CONNECTED: - drdynvc->channel_error = drdynvc_virtual_channel_event_connected(drdynvc, pData, dataLength); - return ; + if ((error = drdynvc_virtual_channel_event_connected(drdynvc, pData, dataLength))) + WLog_ERR(TAG, "drdynvc_virtual_channel_event_connected failed with error %lu", error); break; case CHANNEL_EVENT_DISCONNECTED: - drdynvc->channel_error = drdynvc_virtual_channel_event_disconnected(drdynvc); - return; + if ((error = drdynvc_virtual_channel_event_disconnected(drdynvc))) + WLog_ERR(TAG, "drdynvc_virtual_channel_event_disconnected failed with error %lu", error); break; case CHANNEL_EVENT_TERMINATED: - drdynvc->channel_error = drdynvc_virtual_channel_event_terminated(drdynvc); - return; + if ((error = drdynvc_virtual_channel_event_terminated(drdynvc))) + WLog_ERR(TAG, "drdynvc_virtual_channel_event_terminated failed with error %lu", error); break; } - //TODO signal error + if (error && drdynvc->rdpcontext) + setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_init_event reported an error"); + } /** @@ -1438,6 +1442,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) drdynvc->context = context; context->GetVersion = drdynvc_get_version; + drdynvc->rdpcontext = pEntryPointsEx->context; *(pEntryPointsEx->ppInterface) = (void*) context; } diff --git a/channels/drdynvc/client/drdynvc_main.h b/channels/drdynvc/client/drdynvc_main.h index 0562434..cdd19f9 100644 --- a/channels/drdynvc/client/drdynvc_main.h +++ b/channels/drdynvc/client/drdynvc_main.h @@ -34,6 +34,7 @@ #include #include #include +#include typedef struct drdynvc_plugin drdynvcPlugin; @@ -132,7 +133,8 @@ struct drdynvc_plugin int PriorityCharge1; int PriorityCharge2; int PriorityCharge3; - WIN32ERROR channel_error; + rdpContext* rdpcontext; + IWTSVirtualChannelManager* channel_mgr; }; diff --git a/channels/drdynvc/server/drdynvc_main.c b/channels/drdynvc/server/drdynvc_main.c index f07d2b2..1baebdc 100644 --- a/channels/drdynvc/server/drdynvc_main.c +++ b/channels/drdynvc/server/drdynvc_main.c @@ -108,7 +108,7 @@ static void* drdynvc_server_thread(void* arg) Stream_Free(s, TRUE); ExitThread((DWORD) error); #endif - // WTF ... this code only reads the stream till the stream has no place any more and then exits + // WTF ... this code only reads data into the stream until there is no more memory ExitThread(0); return NULL; } @@ -128,8 +128,6 @@ static WIN32ERROR drdynvc_server_start(DrdynvcServerContext* context) WLog_ERR(TAG, "CreateEvent failed!"); return ERROR_INTERNAL_ERROR; } - // TODO: add mechanism that threads can signal failure - if (!(context->priv->Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL))) { diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index 643192b..b71a2f1 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -61,6 +61,8 @@ struct _DRIVE_DEVICE wMessageQueue* IrpQueue; DEVMAN* devman; + + rdpContext* rdpcontext; }; static UINT32 drive_map_posix_err(int fs_errno) @@ -619,15 +621,23 @@ static void* drive_thread_func(void* arg) IRP* irp; wMessage message; DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg; - WIN32ERROR error; + WIN32ERROR error = CHANNEL_RC_OK; while (1) { if (!MessageQueue_Wait(drive->IrpQueue)) + { + WLog_ERR(TAG, "MessageQueue_Wait failed!"); + error = ERROR_INTERNAL_ERROR; break; + } if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE)) + { + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; break; + } if (message.id == WMQ_QUIT) break; @@ -638,19 +648,24 @@ static void* drive_thread_func(void* arg) if ((error = drive_process_irp(drive, irp))) { WLog_ERR(TAG, "drive_process_irp failed with error %lu!", error); - ExitThread((DWORD)error); - return NULL; + break; } } - ExitThread(0); + if (error && drive->rdpcontext) + setChannelError(drive->rdpcontext, error, "drive_thread_func reported an error"); + ExitThread((DWORD)error); return NULL; } static WIN32ERROR drive_irp_request(DEVICE* device, IRP* irp) { DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device; - MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL); + if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } return CHANNEL_RC_OK; } @@ -704,6 +719,7 @@ WIN32ERROR drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, drive->device.name = name; drive->device.IRPRequest = drive_irp_request; drive->device.Free = drive_free; + drive->rdpcontext = pEntryPoints->rdpcontext; length = (int) strlen(name); drive->device.data = Stream_New(NULL, length + 1); diff --git a/channels/echo/server/echo_main.c b/channels/echo/server/echo_main.c index b0cff2b..ff881bc 100644 --- a/channels/echo/server/echo_main.c +++ b/channels/echo/server/echo_main.c @@ -111,8 +111,7 @@ static void* echo_server_thread_func(void* arg) { IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED); WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error); - ExitThread((DWORD)error); - return NULL; + goto out; } buffer = NULL; @@ -205,10 +204,13 @@ static void* echo_server_thread_func(void* arg) break; } } - Stream_Free(s, TRUE); WTSVirtualChannelClose(echo->echo_channel); echo->echo_channel = NULL; +out: + if (error && echo->context.rdpcontext) + setChannelError(echo->context.rdpcontext, error, "echo_server_thread_func reported an error"); + ExitThread((DWORD)error); return NULL; } diff --git a/channels/encomsp/client/encomsp_main.c b/channels/encomsp/client/encomsp_main.c index 24ea995..a4884a1 100644 --- a/channels/encomsp/client/encomsp_main.c +++ b/channels/encomsp/client/encomsp_main.c @@ -974,7 +974,11 @@ static WIN32ERROR encomsp_virtual_channel_event_data_received(encomspPlugin* enc Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - MessageQueue_Post(encomsp->queue, NULL, 0, (void*) data_in, NULL); + if (!MessageQueue_Post(encomsp->queue, NULL, 0, (void*) data_in, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } } return CHANNEL_RC_OK; } @@ -983,26 +987,21 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { encomspPlugin* encomsp; + WIN32ERROR error = CHANNEL_RC_OK; encomsp = (encomspPlugin*) encomsp_get_open_handle_data(openHandle); if (!encomsp) { WLog_ERR(TAG, "encomsp_virtual_channel_open_event: error no match"); - encomsp->error = CHANNEL_RC_BAD_CHANNEL; return; } - encomsp->error = CHANNEL_RC_OK; - switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - if ((encomsp->error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, totalLength, dataFlags))) - { - WLog_ERR(TAG, "encomsp_virtual_channel_event_data_received failed with error %lu", encomsp->error); - return; - } + if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "encomsp_virtual_channel_event_data_received failed with error %lu", error); break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -1012,8 +1011,10 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT case CHANNEL_EVENT_USER: break; } + if (error && encomsp->rdpcontext) + setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_open_event reported an error"); + return; - //TODO erport error } static void* encomsp_virtual_channel_client_thread(void* arg) @@ -1028,25 +1029,36 @@ static void* encomsp_virtual_channel_client_thread(void* arg) while (1) { if (!MessageQueue_Wait(encomsp->queue)) + { + WLog_ERR(TAG, "MessageQueue_Wait failed!"); + error = ERROR_INTERNAL_ERROR; break; + } - if (MessageQueue_Peek(encomsp->queue, &message, TRUE)) + if (!MessageQueue_Peek(encomsp->queue, &message, TRUE)) { - if (message.id == WMQ_QUIT) - break; + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; + break; + } + + if (message.id == WMQ_QUIT) + break; - if (message.id == 0) + if (message.id == 0) + { + data = (wStream*) message.wParam; + if ((error = encomsp_process_receive(encomsp, data))) { - data = (wStream*) message.wParam; - if ((error = encomsp_process_receive(encomsp, data))) - { - WLog_ERR(TAG, "encomsp_process_receive failed with error %lu!", error); - break; - } + WLog_ERR(TAG, "encomsp_process_receive failed with error %lu!", error); + break; } } } + if (error && encomsp->rdpcontext) + setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_client_thread reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -1131,34 +1143,26 @@ static WIN32ERROR encomsp_virtual_channel_event_terminated(encomspPlugin* encoms static void VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { encomspPlugin* encomsp; + WIN32ERROR error = CHANNEL_RC_OK; encomsp = (encomspPlugin*) encomsp_get_init_handle_data(pInitHandle); if (!encomsp) { WLog_ERR(TAG, "encomsp_virtual_channel_init_event: error no match"); - encomsp->error = CHANNEL_RC_BAD_CHANNEL; return; } - encomsp->error = CHANNEL_RC_OK; - switch (event) { case CHANNEL_EVENT_CONNECTED: - if ((encomsp->error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength))) - { - WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu", encomsp->error); - return; - } + if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength))) + WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu", error); break; case CHANNEL_EVENT_DISCONNECTED: - if ((encomsp->error = encomsp_virtual_channel_event_disconnected(encomsp))) - { - WLog_ERR(TAG, "encomsp_virtual_channel_event_disconnected failed with error %lu", encomsp->error); - return; - } + if ((error = encomsp_virtual_channel_event_disconnected(encomsp))) + WLog_ERR(TAG, "encomsp_virtual_channel_event_disconnected failed with error %lu", error); break; case CHANNEL_EVENT_TERMINATED: @@ -1166,11 +1170,13 @@ static void VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UIN break; default: WLog_ERR(TAG, "uknown event type %d", event); - encomsp->error = ERROR_INVALID_DATA; - return; + error = ERROR_INVALID_DATA; } + + if (error && encomsp->rdpcontext) + setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_init_event reported an error"); + return; - //TODO report error } /* encomsp is always built-in */ @@ -1183,6 +1189,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) EncomspClientContext* context; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; BOOL isFreerdp = FALSE; + WIN32ERROR error; encomsp = (encomspPlugin*) calloc(1, sizeof(encomspPlugin)); if (!encomsp) @@ -1227,6 +1234,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) *(pEntryPointsEx->ppInterface) = (void*) context; encomsp->context = context; + encomsp->rdpcontext = pEntryPointsEx->context; isFreerdp = TRUE; } @@ -1244,9 +1252,9 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) encomsp->channelEntryPoints.pInterface = *(encomsp->channelEntryPoints.ppInterface); encomsp->channelEntryPoints.ppInterface = &(encomsp->channelEntryPoints.pInterface); - if ((encomsp->error = encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp))) + if ((error = encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp))) { - WLog_ERR(TAG, "encomsp_add_init_handle_data failed with error %lu!", encomsp->error); + WLog_ERR(TAG, "encomsp_add_init_handle_data failed with error %lu!", error); goto error_out; } diff --git a/channels/encomsp/client/encomsp_main.h b/channels/encomsp/client/encomsp_main.h index 5aea1b2..e226d96 100644 --- a/channels/encomsp/client/encomsp_main.h +++ b/channels/encomsp/client/encomsp_main.h @@ -49,7 +49,7 @@ struct encomsp_plugin void* InitHandle; DWORD OpenHandle; wMessageQueue* queue; - WIN32ERROR error; + rdpContext* rdpcontext; }; typedef struct encomsp_plugin encomspPlugin; diff --git a/channels/encomsp/server/encomsp_main.c b/channels/encomsp/server/encomsp_main.c index 6547815..02ac629 100644 --- a/channels/encomsp/server/encomsp_main.c +++ b/channels/encomsp/server/encomsp_main.c @@ -179,8 +179,8 @@ static void* encomsp_server_thread(void* arg) if (!s) { WLog_ERR(TAG, "Stream_New failed!"); - ExitThread((DWORD) CHANNEL_RC_NO_MEMORY); - return NULL; + error = CHANNEL_RC_NO_MEMORY; + goto out; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) @@ -240,6 +240,10 @@ static void* encomsp_server_thread(void* arg) } Stream_Free(s, TRUE); +out: + if (error && context->rdpcontext) + setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error"); + ExitThread((DWORD)error); return NULL; } diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index 0d264fc..3991ddf 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -70,6 +70,7 @@ struct _PARALLEL_DEVICE HANDLE thread; wMessageQueue* queue; + rdpContext* rdpcontext; }; typedef struct _PARALLEL_DEVICE PARALLEL_DEVICE; @@ -224,7 +225,7 @@ static WIN32ERROR parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, return irp->Complete(irp); } -static int parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) +static WIN32ERROR parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) { WIN32ERROR error; @@ -312,6 +313,9 @@ static void* parallel_thread_func(void* arg) break; } } + if (error && parallel->rdpcontext) + setChannelError(parallel->rdpcontext, error, "parallel_thread_func reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -320,7 +324,11 @@ static WIN32ERROR parallel_irp_request(DEVICE* device, IRP* irp) { PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; - MessageQueue_Post(parallel->queue, NULL, 0, (void*) irp, NULL); + if (!MessageQueue_Post(parallel->queue, NULL, 0, (void*) irp, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } return CHANNEL_RC_OK; } @@ -375,6 +383,7 @@ WIN32ERROR DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) parallel->device.name = name; parallel->device.IRPRequest = parallel_irp_request; parallel->device.Free = parallel_free; + parallel->rdpcontext = pEntryPoints->rdpcontext; length = strlen(name); parallel->device.data = Stream_New(NULL, length + 1); diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 644e471..b479c60 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -62,6 +62,7 @@ struct _PRINTER_DEVICE HANDLE stopEvent; HANDLE thread; + rdpContext* rdpcontext; }; static WIN32ERROR printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp) @@ -225,6 +226,8 @@ static void* printer_thread_func(void* arg) break; } } + if (error && printer_dev->rdpcontext) + setChannelError(printer_dev->rdpcontext, error, "printer_thread_func reported an error"); ExitThread((DWORD) error); @@ -299,6 +302,7 @@ WIN32ERROR printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinte printer_dev->device.name = port; printer_dev->device.IRPRequest = printer_irp_request; printer_dev->device.Free = printer_free; + printer_dev->rdpcontext = pEntryPoints->rdpcontext; printer_dev->printer = printer; diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index 6af3b5f..10168c0 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -401,7 +401,7 @@ WIN32ERROR rail_add_open_handle_data(DWORD openHandle, void* pUserData) return CHANNEL_RC_NO_MEMORY; } - ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData); + if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData)) { WLog_ERR(TAG, "ListDictionary_Add failed!"); return ERROR_INTERNAL_ERROR; @@ -471,7 +471,11 @@ static WIN32ERROR rail_virtual_channel_event_data_received(railPlugin* rail, Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - MessageQueue_Post(rail->queue, NULL, 0, (void*) data_in, NULL); + if (!MessageQueue_Post(rail->queue, NULL, 0, (void*) data_in, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } } return CHANNEL_RC_OK; } @@ -480,25 +484,21 @@ static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle, UINT eve LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { railPlugin* rail; + WIN32ERROR error = CHANNEL_RC_OK; rail = (railPlugin*) rail_get_open_handle_data(openHandle); if (!rail) { WLog_ERR(TAG, "rail_virtual_channel_open_event: error no match"); - rail->error = CHANNEL_RC_BAD_CHANNEL; return; } - rail->error = CHANNEL_RC_OK; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - if ((rail->error = rail_virtual_channel_event_data_received(rail, pData, dataLength, totalLength, dataFlags))) - { - WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!", rail->error); - return; - } + if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!", error); break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -508,8 +508,11 @@ static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle, UINT eve case CHANNEL_EVENT_USER: break; } + + if (error && rail->rdpcontext) + setChannelError(rail->rdpcontext, error, "rail_virtual_channel_open_event reported an error"); + return; - //TODO report error } static void* rail_virtual_channel_client_thread(void* arg) @@ -522,25 +525,35 @@ static void* rail_virtual_channel_client_thread(void* arg) while (1) { if (!MessageQueue_Wait(rail->queue)) + { + WLog_ERR(TAG, "MessageQueue_Wait failed!"); + error = ERROR_INTERNAL_ERROR; break; + } - if (MessageQueue_Peek(rail->queue, &message, TRUE)) + if (!MessageQueue_Peek(rail->queue, &message, TRUE)) { - if (message.id == WMQ_QUIT) - break; + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; + break; + } + if (message.id == WMQ_QUIT) + break; - if (message.id == 0) + if (message.id == 0) + { + data = (wStream*) message.wParam; + if ((error = rail_order_recv(rail, data))) { - data = (wStream*) message.wParam; - if ((error = rail_order_recv(rail, data))) - { - WLog_ERR(TAG, "rail_order_recv failed with error %d!", error); - break; - } + WLog_ERR(TAG, "rail_order_recv failed with error %d!", error); + break; } } } + if (error && rail->rdpcontext) + setChannelError(rail->rdpcontext, error, "rail_virtual_channel_client_thread reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -620,24 +633,22 @@ static void rail_virtual_channel_event_terminated(railPlugin* rail) static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { railPlugin* rail; + WIN32ERROR error = CHANNEL_RC_OK; rail = (railPlugin*) rail_get_init_handle_data(pInitHandle); if (!rail) { WLog_ERR(TAG, "rail_virtual_channel_init_event: error no match"); - rail->error = CHANNEL_RC_BAD_CHANNEL; return; } - rail->error = CHANNEL_RC_OK; - switch (event) { case CHANNEL_EVENT_CONNECTED: - if ((rail->error = rail_virtual_channel_event_connected(rail, pData, dataLength))) + if ((error = rail_virtual_channel_event_connected(rail, pData, dataLength))) { - WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!", rail->error); + WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!", error); return; } break; @@ -650,8 +661,11 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT e rail_virtual_channel_event_terminated(rail); break; } + + if(error && rail->rdpcontext) + setChannelError(rail->rdpcontext, error, "rail_virtual_channel_init_event reported an error"); + return; - //TODO report error } /* rail is always built-in */ @@ -717,6 +731,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) context->ServerExecuteResult = rail_server_execute_result; context->ClientGetAppIdRequest = rail_client_get_appid_request; context->ServerGetAppIdResponse = rail_server_get_appid_response; + rail->rdpcontext = pEntryPointsEx->context; *(pEntryPointsEx->ppInterface) = (void*) context; rail->context = context; diff --git a/channels/rail/client/rail_main.h b/channels/rail/client/rail_main.h index 62d1d55..91a15ae 100644 --- a/channels/rail/client/rail_main.h +++ b/channels/rail/client/rail_main.h @@ -49,7 +49,7 @@ struct rail_plugin void* InitHandle; DWORD OpenHandle; wMessageQueue* queue; - WIN32ERROR error; + rdpContext* rdpcontext; }; typedef struct rail_plugin railPlugin; diff --git a/channels/rdpdr/client/devman.c b/channels/rdpdr/client/devman.c index 7086521..02069c4 100644 --- a/channels/rdpdr/client/devman.c +++ b/channels/rdpdr/client/devman.c @@ -120,7 +120,7 @@ static char SMARTCARD_SERVICE_NAME[] = "smartcard"; static char SERIAL_SERVICE_NAME[] = "serial"; static char PARALLEL_SERVICE_NAME[] = "parallel"; -WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device) +WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext) { char* ServiceName = NULL; DEVICE_SERVICE_ENTRY_POINTS ep; @@ -155,8 +155,7 @@ WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device) ep.devman = devman; ep.RegisterDevice = devman_register_device; ep.device = device; + ep.rdpcontext = rdpcontext; - entry(&ep); - - return CHANNEL_RC_OK; + return entry(&ep); } diff --git a/channels/rdpdr/client/devman.h b/channels/rdpdr/client/devman.h index 0db2c13..d5589b5 100644 --- a/channels/rdpdr/client/devman.h +++ b/channels/rdpdr/client/devman.h @@ -26,7 +26,7 @@ #include "rdpdr_main.h" void devman_unregister_device(DEVMAN* devman, void* key); -WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device); +WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext); DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id); DEVMAN* devman_new(rdpdrPlugin* rdpdr); diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 939cc95..54aa5da 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -129,7 +129,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) drive->Path = _strdup(drive_path); drive_path[1] = '\0'; drive->Name = _strdup(drive_path); - devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive); + devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext); rdpdr_send_device_list_announce_request(rdpdr, TRUE); } unitmask = unitmask >> 1; @@ -464,7 +464,7 @@ static WIN32ERROR handle_hotplug(rdpdrPlugin* rdpdr) free(drive); return CHANNEL_RC_NO_MEMORY; } - if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive))) + if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext))) { WLog_ERR(TAG, "devman_load_device_service failed!"); free(drive->Path); @@ -596,7 +596,7 @@ static WIN32ERROR rdpdr_process_connect(rdpdrPlugin* rdpdr) continue; } - if ((error = devman_load_device_service(rdpdr->devman, device))) + if ((error = devman_load_device_service(rdpdr->devman, device, rdpdr->rdpcontext))) { WLog_ERR(TAG, "devman_load_device_service failed with error %lu!", error); return error; @@ -895,9 +895,9 @@ static WIN32ERROR rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) if ((error = rdpdr_process_irp(rdpdr, s))) { WLog_ERR(TAG, "rdpdr_process_irp failed with error %lu", error); - s = NULL; return error; } + s = NULL; break; default: @@ -1083,7 +1083,11 @@ static WIN32ERROR rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - MessageQueue_Post(rdpdr->queue, NULL, 0, (void*) data_in, NULL); + if (!MessageQueue_Post(rdpdr->queue, NULL, 0, (void*) data_in, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } } return CHANNEL_RC_OK; } @@ -1092,25 +1096,21 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT ev LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpdrPlugin* rdpdr; + WIN32ERROR error = CHANNEL_RC_OK; rdpdr = (rdpdrPlugin*) rdpdr_get_open_handle_data(openHandle); if (!rdpdr) { WLog_ERR(TAG, "rdpdr_virtual_channel_open_event: error no match"); - rdpdr->error = CHANNEL_RC_BAD_CHANNEL; return; } - rdpdr->error = CHANNEL_RC_OK; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - if ((rdpdr->error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags))) - { - WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received failed with error %lu!", rdpdr->error ); - return; - } + if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received failed with error %lu!", error ); break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -1120,8 +1120,10 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT ev case CHANNEL_EVENT_USER: break; } + if (error && rdpdr->rdpcontext) + setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_open_event reported an error"); + return; - //TODO report error } static void* rdpdr_virtual_channel_client_thread(void* arg) @@ -1129,11 +1131,13 @@ static void* rdpdr_virtual_channel_client_thread(void* arg) wStream* data; wMessage message; rdpdrPlugin* rdpdr = (rdpdrPlugin*) arg; - int error; + WIN32ERROR error; if ((error = rdpdr_process_connect(rdpdr))) { WLog_ERR(TAG, "rdpdr_process_connect failed with error %lu!", error); + if (rdpdr->rdpcontext) + setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_client_thread reported an error"); ExitThread((DWORD) error); return NULL; } @@ -1154,6 +1158,8 @@ static void* rdpdr_virtual_channel_client_thread(void* arg) if ((error = rdpdr_process_receive(rdpdr, data))) { WLog_ERR(TAG, "rdpdr_process_receive failed with error %lu!", error); + if (rdpdr->rdpcontext) + setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_client_thread reported an error"); ExitThread((DWORD) error); return NULL; } @@ -1250,34 +1256,28 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr) static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { rdpdrPlugin* rdpdr; + WIN32ERROR error = CHANNEL_RC_OK; rdpdr = (rdpdrPlugin*) rdpdr_get_init_handle_data(pInitHandle); if (!rdpdr) { - WLog_ERR(TAG, "rdpdr_virtual_channel_init_event: error no match"); - rdpdr->error = CHANNEL_RC_BAD_CHANNEL; + WLog_ERR(TAG, "error no match"); return; } - rdpdr->error = CHANNEL_RC_OK; - switch (event) { + case CHANNEL_EVENT_INITIALIZED: + break; case CHANNEL_EVENT_CONNECTED: - if ((rdpdr->error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) - { - WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!", rdpdr->error); - return; - } + if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!", error); break; case CHANNEL_EVENT_DISCONNECTED: - if ((rdpdr->error = rdpdr_virtual_channel_event_disconnected(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!", rdpdr->error); - return; - } + if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!", error); break; case CHANNEL_EVENT_TERMINATED: @@ -1285,11 +1285,13 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT break; default: WLog_ERR(TAG, "unknown event %d!", event); - rdpdr->error = ERROR_INVALID_DATA; + error = ERROR_INVALID_DATA; break; } + + if (error && rdpdr->rdpcontext) + setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_init_event reported an error"); return; - //TODO report error } /* rdpdr is always built-in */ @@ -1299,6 +1301,8 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { UINT rc; rdpdrPlugin* rdpdr; + CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; + rdpdr = (rdpdrPlugin*) calloc(1, sizeof(rdpdrPlugin)); @@ -1317,6 +1321,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) rdpdr->sequenceId = 0; + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints; + + if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) && + (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) + { + + rdpdr->rdpcontext = pEntryPointsEx->context; + } + CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index 39fbc58..8ba82fa 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -67,7 +67,7 @@ struct rdpdr_plugin #else HANDLE stopEvent; #endif - WIN32ERROR error; + rdpContext* rdpcontext; }; WIN32ERROR rdpdr_send(rdpdrPlugin* rdpdr, wStream* s); diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c index 5df576c..b2ec4cf 100644 --- a/channels/rdpdr/server/rdpdr_main.c +++ b/channels/rdpdr/server/rdpdr_main.c @@ -947,8 +947,8 @@ static void* rdpdr_server_thread(void* arg) if (!s) { WLog_ERR(TAG, "Stream_New failed!"); - ExitThread((DWORD) CHANNEL_RC_NO_MEMORY); - return NULL; + error = CHANNEL_RC_NO_MEMORY; + goto out; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) @@ -965,9 +965,7 @@ static void* rdpdr_server_thread(void* arg) if ((error = rdpdr_server_send_announce_request(context))) { WLog_ERR(TAG, "rdpdr_server_send_announce_request failed with error %lu!", error); - Stream_Free(s, TRUE); - ExitThread((DWORD) error); - return NULL; + goto out_stream; } while (1) @@ -976,14 +974,13 @@ static void* rdpdr_server_thread(void* arg) status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) - { break; - } if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); + error = ERROR_INTERNAL_ERROR; break; } @@ -1001,16 +998,18 @@ static void* rdpdr_server_thread(void* arg) if ((error = rdpdr_server_receive_pdu(context, s, &header))) { WLog_ERR(TAG, "rdpdr_server_receive_pdu failed with error %lu!", error); - Stream_Free(s, TRUE); - ExitThread((DWORD) error); - return NULL; + goto out_stream; } } } } - +out_stream: Stream_Free(s, TRUE); - ExitThread((DWORD) CHANNEL_RC_OK); +out: + if (error && context->rdpcontext) + setChannelError(context->rdpcontext, error, "rdpdr_server_thread reported an error"); + + ExitThread((DWORD) error); return NULL; } diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index adf549a..15db248 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -36,6 +36,7 @@ #include #include +#include #include "rdpei_common.h" @@ -105,6 +106,7 @@ struct _RDPEI_PLUGIN HANDLE thread; CRITICAL_SECTION lock; + rdpContext* rdpcontext; }; typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN; @@ -162,19 +164,19 @@ static void* rdpei_schedule_thread(void* arg) RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg; RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface; HANDLE hdl[] = {rdpei->event, rdpei->stopEvent}; - WIN32ERROR error; + WIN32ERROR error = CHANNEL_RC_OK; if (!rdpei) { - ExitThread((DWORD)ERROR_INVALID_PARAMETER); - return NULL; + error = ERROR_INVALID_PARAMETER; + goto out; } if (!context) { - ExitThread((DWORD)ERROR_INVALID_PARAMETER); - return NULL; + error = ERROR_INVALID_PARAMETER; + goto out; } while (1) @@ -188,8 +190,7 @@ static void* rdpei_schedule_thread(void* arg) if ((error = rdpei_add_frame(context))) { WLog_ERR(TAG, "rdpei_add_frame failed with error %lu!", error); - ExitThread((DWORD)error); - return NULL; + break; } if (rdpei->frame.contactCount > 0) @@ -197,18 +198,20 @@ static void* rdpei_schedule_thread(void* arg) if ((error = rdpei_send_frame(context))) { WLog_ERR(TAG, "rdpei_send_frame failed with error %lu!", error); - ExitThread((DWORD)error); - return NULL; + break; } } - if (status == WAIT_OBJECT_0) ResetEvent(rdpei->event); LeaveCriticalSection(&rdpei->lock); } +out: + if (error && rdpei->rdpcontext) + setChannelError(rdpei->rdpcontext, error, "rdpei_schedule_thread reported an error"); + ExitThread(0); return NULL; @@ -874,6 +877,10 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) rdpei->maxTouchContacts = 10; size = rdpei->maxTouchContacts * sizeof(RDPINPUT_CONTACT_POINT); rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*) calloc(1, size); + + rdpei->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context; + + if (!rdpei->contactPoints) { WLog_ERR(TAG, "calloc failed!"); diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 2db0ee3..580f256 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -1381,6 +1381,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600; + context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext)); if (!context) diff --git a/channels/rdpgfx/client/rdpgfx_main.h b/channels/rdpgfx/client/rdpgfx_main.h index 96d91b4..380292d 100644 --- a/channels/rdpgfx/client/rdpgfx_main.h +++ b/channels/rdpgfx/client/rdpgfx_main.h @@ -30,6 +30,7 @@ #include #include #include +#include #define TAG CHANNELS_TAG("rdpgfx.client") @@ -77,6 +78,7 @@ struct _RDPGFX_PLUGIN UINT16 MaxCacheSlot; void* CacheSlots[25600]; + rdpContext* rdpcontext; }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; diff --git a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c index 1f395be..7a6d324 100644 --- a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c +++ b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c @@ -4,6 +4,8 @@ * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -601,7 +603,7 @@ static COMMAND_LINE_ARGUMENT_A rdpsnd_alsa_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args) +static WIN32ERROR rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args) { int status; DWORD flags; @@ -612,7 +614,10 @@ static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_alsa_args, flags, alsa, NULL, NULL); if (status < 0) - return status; + { + WLog_ERR(TAG, "CommandLineParseArgumentsA failed!"); + return CHANNEL_RC_INITIALIZATION_ERROR; + } arg = rdpsnd_alsa_args; @@ -634,21 +639,25 @@ static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); - return status; + return CHANNEL_RC_OK; } #ifdef STATIC_CHANNELS #define freerdp_rdpsnd_client_subsystem_entry alsa_freerdp_rdpsnd_client_subsystem_entry #endif -int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; rdpsndAlsaPlugin* alsa; + WIN32ERROR error; alsa = (rdpsndAlsaPlugin*) calloc(1, sizeof(rdpsndAlsaPlugin)); if (!alsa) - return -1; + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } alsa->device.Open = rdpsnd_alsa_open; alsa->device.FormatSupported = rdpsnd_alsa_format_supported; @@ -661,14 +670,22 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE alsa->device.Free = rdpsnd_alsa_free; args = pEntryPoints->args; - if (rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin*) alsa, args) != 0) + if ((error = rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin*) alsa, args))) + { + WLog_ERR(TAG, "rdpsnd_alsa_parse_addin_args failed with error %lu", error); goto error_parse_args; + } + if (!alsa->device_name) { alsa->device_name = _strdup("default"); if (!alsa->device_name) + { + WLog_ERR(TAG, "_strdup failed!"); + error = CHANNEL_RC_NO_MEMORY; goto error_strdup; + } } alsa->pcm_handle = 0; @@ -681,11 +698,15 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE alsa->dsp_context = freerdp_dsp_context_new(); if (!alsa->dsp_context) + { + WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); + error = CHANNEL_RC_NO_MEMORY; goto error_dsp_context; + } pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) alsa); - return 0; + return CHANNEL_RC_OK; error_dsp_context: free(alsa->device_name); @@ -693,5 +714,5 @@ error_strdup: free(alsa->device_name); error_parse_args: free(alsa); - return -1; + return error; } diff --git a/channels/rdpsnd/client/ios/rdpsnd_ios.c b/channels/rdpsnd/client/ios/rdpsnd_ios.c index f0ede99..2266864 100644 --- a/channels/rdpsnd/client/ios/rdpsnd_ios.c +++ b/channels/rdpsnd/client/ios/rdpsnd_ios.c @@ -3,6 +3,8 @@ * Audio Output Virtual Channel * * Copyright 2013 Dell Software + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +27,7 @@ #include #include +#include #import @@ -281,12 +284,12 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device) #define freerdp_rdpsnd_client_subsystem_entry ios_freerdp_rdpsnd_client_subsystem_entry #endif -int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { rdpsndIOSPlugin* p = (rdpsndIOSPlugin*) calloc(1, sizeof(rdpsndIOSPlugin)); if (!p) - return -1; + return CHANNEL_RC_NO_MEMORY; p->device.Open = rdpsnd_ios_open; p->device.FormatSupported = rdpsnd_ios_format_supported; @@ -299,5 +302,5 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p); - return 0; + return CHANNEL_RC_OK; } diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index 1c9394d..5677235 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -3,6 +3,8 @@ * Audio Output Virtual Channel * * Copyright 2012 Laxmikant Rashinkar + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +31,7 @@ #include #include +#include #include #include @@ -133,7 +136,7 @@ static BOOL rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in UInt32 DecodeBufferSizeFrames; UInt32 propertySize = sizeof(DecodeBufferSizeFrames); - AudioQueueGetProperty(mac->audioQueue, + status = AudioQueueGetProperty(mac->audioQueue, kAudioQueueProperty_DecodeBufferSizeFrames, &DecodeBufferSizeFrames, &propertySize); @@ -288,14 +291,14 @@ static void rdpsnd_mac_play(rdpsndDevicePlugin* device, BYTE* data, int size) #define freerdp_rdpsnd_client_subsystem_entry mac_freerdp_rdpsnd_client_subsystem_entry #endif -int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { rdpsndMacPlugin* mac; mac = (rdpsndMacPlugin*) calloc(1, sizeof(rdpsndMacPlugin)); if (!mac) - return -1; + return CHANNEL_RC_NO_MEMORY; mac->device.Open = rdpsnd_mac_open; mac->device.FormatSupported = rdpsnd_mac_format_supported; @@ -308,5 +311,5 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac); - return 0; + return CHANNEL_RC_OK; } diff --git a/channels/rdpsnd/client/opensles/rdpsnd_opensles.c b/channels/rdpsnd/client/opensles/rdpsnd_opensles.c index 9d920ec..4fd790b 100644 --- a/channels/rdpsnd/client/opensles/rdpsnd_opensles.c +++ b/channels/rdpsnd/client/opensles/rdpsnd_opensles.c @@ -3,6 +3,8 @@ * Audio Output Virtual Channel * * Copyright 2013 Armin Novak + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +34,7 @@ #include #include #include +#include #include #include @@ -432,16 +435,18 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device, opensles_freerdp_rdpsnd_client_subsystem_entry #endif -int freerdp_rdpsnd_client_subsystem_entry( +WIN32ERROR freerdp_rdpsnd_client_subsystem_entry( PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; rdpsndopenslesPlugin* opensles; + WIN32ERROR error; DEBUG_SND("pEntryPoints=%p", pEntryPoints); - opensles = (rdpsndopenslesPlugin*) malloc(sizeof(rdpsndopenslesPlugin)); - ZeroMemory(opensles, sizeof(rdpsndopenslesPlugin)); + opensles = (rdpsndopenslesPlugin*) calloc(1, sizeof(rdpsndopenslesPlugin)); + if (!opensles) + return CHANNEL_RC_NO_MEMORY; opensles->device.Open = rdpsnd_opensles_open; opensles->device.FormatSupported = rdpsnd_opensles_format_supported; @@ -460,7 +465,10 @@ int freerdp_rdpsnd_client_subsystem_entry( { opensles->device_name = _strdup("default"); if (!opensles->device_name) - return ERROR_OUTOFMEMORY; + { + error = CHANNEL_RC_NO_MEMORY; + goto outstrdup; + } } opensles->rate = 44100; @@ -468,10 +476,20 @@ int freerdp_rdpsnd_client_subsystem_entry( opensles->format = WAVE_FORMAT_ADPCM; opensles->dsp_context = freerdp_dsp_context_new(); + if (!opensles->dsp_context) + { + error = CHANNEL_RC_NO_MEMORY; + goto out_dsp_new; + } pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) opensles); DEBUG_SND("success"); - return 0; + return CHANNEL_RC_OK; +out_dsp_new: + free(opensles->device_name); +outstrdup: + free(opensles); + return error; } diff --git a/channels/rdpsnd/client/oss/rdpsnd_oss.c b/channels/rdpsnd/client/oss/rdpsnd_oss.c index 81aa4c8..df99c46 100644 --- a/channels/rdpsnd/client/oss/rdpsnd_oss.c +++ b/channels/rdpsnd/client/oss/rdpsnd_oss.c @@ -3,6 +3,8 @@ * Audio Output Virtual Channel * * Copyright (c) 2015 Rozhuk Ivan + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -434,12 +436,13 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin *device, ADDIN_ARGV *a #define freerdp_rdpsnd_client_subsystem_entry oss_freerdp_rdpsnd_client_subsystem_entry #endif -int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { +WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV *args; rdpsndOssPlugin *oss; - oss = (rdpsndOssPlugin*)malloc(sizeof(rdpsndOssPlugin)); - ZeroMemory(oss, sizeof(rdpsndOssPlugin)); + oss = (rdpsndOssPlugin*)calloc(1, sizeof(rdpsndOssPlugin)); + if (!oss) + return CHANNEL_RC_NO_MEMORY; oss->device.Open = rdpsnd_oss_open; oss->device.FormatSupported = rdpsnd_oss_format_supported; @@ -459,8 +462,13 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE rdpsnd_oss_parse_addin_args((rdpsndDevicePlugin*)oss, args); oss->dsp_context = freerdp_dsp_context_new(); + if (!oss->dsp_context) + { + free(oss); + return CHANNEL_RC_NO_MEMORY; + } pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)oss); - return 0; + return CHANNEL_RC_OK; } diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index c53991d..092a768 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -3,6 +3,8 @@ * Audio Output Virtual Channel * * Copyright 2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +39,7 @@ #include #include +#include #include "rdpsnd_main.h" @@ -631,7 +634,7 @@ static WIN32ERROR rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDI #define freerdp_rdpsnd_client_subsystem_entry pulse_freerdp_rdpsnd_client_subsystem_entry #endif -int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; rdpsndPulsePlugin* pulse; @@ -639,7 +642,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE pulse = (rdpsndPulsePlugin*) calloc(1, sizeof(rdpsndPulsePlugin)); if (!pulse) - return -1; + return CHANNEL_RC_NO_MEMORY; pulse->device.Open = rdpsnd_pulse_open; pulse->device.FormatSupported = rdpsnd_pulse_format_supported; @@ -658,7 +661,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE goto error; } - ret = ERROR_OUTOFMEMORY; + ret = CHANNEL_RC_NO_MEMORY; pulse->dsp_context = freerdp_dsp_context_new(); if (!pulse->dsp_context) goto error; diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 246a0ac..0c40ad0 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -5,6 +5,8 @@ * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * Copyright 2012-2013 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,6 +95,7 @@ struct rdpsnd_plugin /* Device plugin */ rdpsndDevicePlugin* device; + rdpContext* rdpcontext; }; static WIN32ERROR rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave); @@ -106,6 +109,7 @@ static void* rdpsnd_schedule_thread(void* arg) RDPSND_WAVE* wave; rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg; HANDLE events[2]; + WIN32ERROR error = CHANNEL_RC_OK; events[0] = MessageQueue_Event(rdpsnd->MsgPipe->Out); events[1] = rdpsnd->stopEvent; @@ -113,7 +117,11 @@ static void* rdpsnd_schedule_thread(void* arg) while (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0) { if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE)) + { + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; break; + } if (message.id == WMQ_QUIT) break; @@ -128,18 +136,20 @@ static void* rdpsnd_schedule_thread(void* arg) Sleep(wTimeDiff); } - if (rdpsnd_confirm_wave(rdpsnd, wave) != CHANNEL_RC_OK) + if ((error = rdpsnd_confirm_wave(rdpsnd, wave))) { WLog_ERR(TAG, "error confirming wave"); break; } - message.wParam = NULL; free(wave); } - ExitThread(0); + if (error && rdpsnd->rdpcontext) + setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_schedule_thread reported an error"); + + ExitThread((DWORD)error); return NULL; } @@ -149,7 +159,10 @@ WIN32ERROR rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd) pdu = Stream_New(NULL, 8); if (!pdu) + { + WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; + } Stream_Write_UINT8(pdu, SNDC_QUALITYMODE); /* msgType */ Stream_Write_UINT8(pdu, 0); /* bPad */ Stream_Write_UINT16(pdu, 4); /* BodySize */ @@ -244,7 +257,10 @@ WIN32ERROR rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd) pdu = Stream_New(NULL, length); if (!pdu) + { + WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; + } Stream_Write_UINT8(pdu, SNDC_FORMATS); /* msgType */ Stream_Write_UINT8(pdu, 0); /* bPad */ @@ -370,7 +386,10 @@ WIN32ERROR rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeSt pdu = Stream_New(NULL, 8); if (!pdu) + { + WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; + } Stream_Write_UINT8(pdu, SNDC_TRAINING); /* msgType */ Stream_Write_UINT8(pdu, 0); /* bPad */ @@ -457,7 +476,10 @@ WIN32ERROR rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, pdu = Stream_New(NULL, 8); if (!pdu) + { + WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; + } Stream_Write_UINT8(pdu, SNDC_WAVECONFIRM); Stream_Write_UINT8(pdu, 0); @@ -483,7 +505,10 @@ static WIN32ERROR rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device return rdpsnd_confirm_wave(device->rdpsnd, wave); if (!MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL)) - return CHANNEL_RC_NO_MEMORY; + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } return CHANNEL_RC_OK; @@ -511,9 +536,12 @@ static WIN32ERROR rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s) data = Stream_Buffer(s); size = (int) Stream_Capacity(s); - wave = (RDPSND_WAVE*) malloc(sizeof(RDPSND_WAVE)); + wave = (RDPSND_WAVE*) calloc(1, sizeof(RDPSND_WAVE)); if (!wave) + { + WLog_ERR(TAG, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; + } wave->wLocalTimeA = GetTickCount(); wave->wTimeStampA = rdpsnd->wTimeStamp; @@ -668,27 +696,25 @@ static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlug device->WaveConfirm = rdpsnd_device_send_wave_confirm_pdu; } -static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args) +static WIN32ERROR rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args) { PFREERDP_RDPSND_DEVICE_ENTRY entry; - FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints; + FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;\ + WIN32ERROR error; entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0); if (!entry) - return FALSE; + return ERROR_INTERNAL_ERROR; entryPoints.rdpsnd = rdpsnd; entryPoints.pRegisterRdpsndDevice = rdpsnd_register_device_plugin; entryPoints.args = args; - if (entry(&entryPoints) != 0) - { - WLog_ERR(TAG, "%s entry returns error.", name); - return FALSE; - } + if ((error = entry(&entryPoints))) + WLog_ERR(TAG, "%s entry returns error %lu", name, error); - return TRUE; + return error; } BOOL rdpsnd_set_subsystem(rdpsndPlugin* rdpsnd, const char* subsystem) @@ -819,10 +845,10 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) if (strcmp(rdpsnd->subsystem, "fake") == 0) return CHANNEL_RC_OK; - if (!rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args)) + if ((status = rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args))) { - WLog_ERR(TAG, "unable to load the %s subsystem plugin", rdpsnd->subsystem); - return CHANNEL_RC_INITIALIZATION_ERROR; + WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status); + return status; } } else @@ -832,7 +858,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) { subsystem_name = "ios"; device_name = ""; - rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args); + if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args))) + { + WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status); + return status; + } } #endif @@ -841,7 +871,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) { subsystem_name = "opensles"; device_name = ""; - rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args); + if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args))) + { + WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status); + return status; + } } #endif @@ -850,7 +884,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) { subsystem_name = "pulse"; device_name = ""; - rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args); + if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args))) + { + WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status); + return status; + } } #endif @@ -859,7 +897,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) { subsystem_name = "alsa"; device_name = "default"; - rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args); + if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args))) + { + WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status); + return status; + } } #endif @@ -868,7 +910,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) { subsystem_name = "oss"; device_name = ""; - rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args); + if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args))) + { + WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status); + return status; + } } #endif @@ -878,7 +924,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) { subsystem_name = "mac"; device_name = "default"; - rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args); + if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args))) + { + WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status); + return status; + } } #endif @@ -887,7 +937,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) { subsystem_name = "winmm"; device_name = ""; - rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args); + if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args))) + { + WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status); + return status; + } } #endif @@ -909,13 +963,19 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd) { rdpsnd->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!rdpsnd->stopEvent) + { + WLog_ERR(TAG, "CreateEvent failed!"); return CHANNEL_RC_INITIALIZATION_ERROR; + } rdpsnd->ScheduleThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread, (void*) rdpsnd, 0, NULL); if (!rdpsnd->ScheduleThread) + { + WLog_ERR(TAG, "CreateThread failed!"); return CHANNEL_RC_INITIALIZATION_ERROR; + } } return CHANNEL_RC_OK; @@ -1002,7 +1062,7 @@ void rdpsnd_remove_open_handle_data(DWORD openHandle) WIN32ERROR rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s) { - WIN32ERROR status = CHANNEL_RC_OK; + WIN32ERROR status; if (!rdpsnd) { @@ -1024,14 +1084,14 @@ WIN32ERROR rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s) return status; } -static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin, +static WIN32ERROR rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* s; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { - return; + return CHANNEL_RC_OK; } if (dataFlags & CHANNEL_FLAG_FIRST) @@ -1040,10 +1100,21 @@ static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin, Stream_Free(plugin->data_in, TRUE); plugin->data_in = Stream_New(NULL, totalLength); + if (!plugin->data_in) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } } s = plugin->data_in; - Stream_EnsureRemainingCapacity(s, (int) dataLength); + + if (!Stream_EnsureRemainingCapacity(s, (int) dataLength)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return CHANNEL_RC_NO_MEMORY; + } + Stream_Write(s, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) @@ -1051,20 +1122,27 @@ static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin, if (Stream_Capacity(s) != Stream_GetPosition(s)) { WLog_ERR(TAG, "rdpsnd_virtual_channel_event_data_received: read error"); + return ERROR_INTERNAL_ERROR; } plugin->data_in = NULL; Stream_SealLength(s); Stream_SetPosition(s, 0); - MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL); + if (!MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } } + return CHANNEL_RC_OK; } static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT event, LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpsndPlugin* rdpsnd; + WIN32ERROR error = CHANNEL_RC_OK; rdpsnd = (rdpsndPlugin*) rdpsnd_get_open_handle_data(openHandle); @@ -1077,7 +1155,8 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT e switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - rdpsnd_virtual_channel_event_data_received(rdpsnd, pData, dataLength, totalLength, dataFlags); + if ((error = rdpsnd_virtual_channel_event_data_received(rdpsnd, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "rdpsnd_virtual_channel_event_data_received failed with error %lu", error); break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -1087,6 +1166,9 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT e case CHANNEL_EVENT_USER: break; } + if (error && rdpsnd->rdpcontext) + setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_virtual_channel_open_event reported an error"); + } static void* rdpsnd_virtual_channel_client_thread(void* arg) @@ -1094,8 +1176,9 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg) wStream* data; wMessage message; rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg; + WIN32ERROR error; - if (rdpsnd_process_connect(rdpsnd) != CHANNEL_RC_OK) + if ((error = rdpsnd_process_connect(rdpsnd))) { WLog_ERR(TAG, "error connecting sound channel"); goto out; @@ -1104,71 +1187,86 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg) while (1) { if (!MessageQueue_Wait(rdpsnd->MsgPipe->In)) + { + WLog_ERR(TAG, "MessageQueue_Wait failed!"); + error = ERROR_INTERNAL_ERROR; break; + } - if (MessageQueue_Peek(rdpsnd->MsgPipe->In, &message, TRUE)) + if (!MessageQueue_Peek(rdpsnd->MsgPipe->In, &message, TRUE)) { - if (message.id == WMQ_QUIT) - break; + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; + break; + } + + if (message.id == WMQ_QUIT) + break; - if (message.id == 0) + if (message.id == 0) + { + data = (wStream*) message.wParam; + if ((error = rdpsnd_recv_pdu(rdpsnd, data))) { - data = (wStream*) message.wParam; - if (rdpsnd_recv_pdu(rdpsnd, data) != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "error treating sound channel message"); - break; - } + WLog_ERR(TAG, "error treating sound channel message"); + break; } } } out: + if (error && rdpsnd->rdpcontext) + setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_virtual_channel_client_thread reported an error"); + rdpsnd_process_disconnect(rdpsnd); - ExitThread(0); + ExitThread((DWORD)error); return NULL; } -static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID pData, UINT32 dataLength) +static WIN32ERROR rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID pData, UINT32 dataLength) { UINT32 status; status = plugin->channelEntryPoints.pVirtualChannelOpen(plugin->InitHandle, &plugin->OpenHandle, plugin->channelDef.name, rdpsnd_virtual_channel_open_event); - if (!rdpsnd_add_open_handle_data(plugin->OpenHandle, plugin)) - { - WLog_ERR(TAG, "%s: unable to register opened handle", __FUNCTION__); - return; - } - if (status != CHANNEL_RC_OK) { WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]", WTSErrorToString(status), status); - return; + return status; + } + + if (!rdpsnd_add_open_handle_data(plugin->OpenHandle, plugin)) + { + WLog_ERR(TAG, "unable to register opened handle"); + return ERROR_INTERNAL_ERROR; } plugin->MsgPipe = MessagePipe_New(); if (!plugin->MsgPipe) { - WLog_ERR(TAG, "%s: unable to create message pipe", __FUNCTION__); - return; + WLog_ERR(TAG, "unable to create message pipe"); + return CHANNEL_RC_NO_MEMORY; } plugin->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin, 0, NULL); if (!plugin->thread) { - WLog_ERR(TAG, "%s: unable to create thread", __FUNCTION__); - return; + WLog_ERR(TAG, "unable to create thread"); + MessagePipe_Free(plugin->MsgPipe); + plugin->MsgPipe = NULL; + return ERROR_INTERNAL_ERROR; } + + return CHANNEL_RC_OK; } -static void rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd) +static WIN32ERROR rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd) { - UINT rc; + WIN32ERROR error; MessagePipe_PostQuit(rdpsnd->MsgPipe, 0); WaitForSingleObject(rdpsnd->thread, INFINITE); @@ -1176,11 +1274,12 @@ static void rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd) CloseHandle(rdpsnd->thread); rdpsnd->thread = NULL; - rc = rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle); - if (CHANNEL_RC_OK != rc) + error = rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle); + if (CHANNEL_RC_OK != error) { WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]", - WTSErrorToString(rc), rc); + WTSErrorToString(error), error); + return error; } if (rdpsnd->data_in) @@ -1219,6 +1318,8 @@ static void rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd) } rdpsnd_remove_open_handle_data(rdpsnd->OpenHandle); + + return CHANNEL_RC_OK; } static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) @@ -1231,6 +1332,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { rdpsndPlugin* plugin; + WIN32ERROR error = CHANNEL_RC_OK; plugin = (rdpsndPlugin*) rdpsnd_get_init_handle_data(pInitHandle); @@ -1243,17 +1345,21 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT switch (event) { case CHANNEL_EVENT_CONNECTED: - rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength); + if ((error = rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength))) + WLog_ERR(TAG, "rdpsnd_virtual_channel_event_connected failed with error %lu!", error); break; case CHANNEL_EVENT_DISCONNECTED: - rdpsnd_virtual_channel_event_disconnected(plugin); + if ((error = rdpsnd_virtual_channel_event_disconnected(plugin))) + WLog_ERR(TAG, "rdpsnd_virtual_channel_event_disconnected failed with error %lu!", error); break; case CHANNEL_EVENT_TERMINATED: rdpsnd_virtual_channel_event_terminated(plugin); break; } + if (error && plugin->rdpcontext) + setChannelError(plugin->rdpcontext, error, "rdpsnd_virtual_channel_init_event reported an error"); } /* rdpsnd is always built-in */ @@ -1264,10 +1370,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) UINT rc; rdpsndPlugin* rdpsnd; + CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; + rdpsnd = (rdpsndPlugin*) calloc(1, sizeof(rdpsndPlugin)); if (!rdpsnd) + { + WLog_ERR(TAG, "calloc failed!"); return FALSE; + } #if !defined(_WIN32) && !defined(ANDROID) { @@ -1284,6 +1395,14 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) strcpy(rdpsnd->channelDef.name, "rdpsnd"); + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints; + + if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) && + (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) + { + rdpsnd->rdpcontext = pEntryPointsEx->context; + } + CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client"); diff --git a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c index 0d87185..70e232d 100644 --- a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c +++ b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c @@ -4,6 +4,8 @@ * * Copyright 2009-2012 Jay Sorg * Copyright 2010-2012 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,10 +33,12 @@ #include #include +#include #include #include #include +#include #include "rdpsnd_main.h" @@ -335,7 +339,7 @@ static void rdpsnd_winmm_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV #define freerdp_rdpsnd_client_subsystem_entry winmm_freerdp_rdpsnd_client_subsystem_entry #endif -int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; rdpsndWinmmPlugin* winmm; @@ -343,7 +347,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE winmm = (rdpsndWinmmPlugin*) calloc(1, sizeof(rdpsndWinmmPlugin)); if (!winmm) - return -1; + return CHANNEL_RC_NO_MEMORY; winmm->device.DisableConfirmThread = TRUE; @@ -362,8 +366,13 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE rdpsnd_winmm_parse_addin_args((rdpsndDevicePlugin*) winmm, args); winmm->dsp_context = freerdp_dsp_context_new(); + if (!winmm->dsp_context) + { + free(winmm); + return CHANNEL_RC_NO_MEMORY; + } pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) winmm); - return 0; + return CHANNEL_RC_OK; } diff --git a/channels/rdpsnd/server/rdpsnd_main.c b/channels/rdpsnd/server/rdpsnd_main.c index 50d9d7f..eb9ca01 100644 --- a/channels/rdpsnd/server/rdpsnd_main.c +++ b/channels/rdpsnd/server/rdpsnd_main.c @@ -3,6 +3,8 @@ * Server Audio Virtual Channel * * Copyright 2012 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +35,7 @@ #include "rdpsnd_main.h" -BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) +WIN32ERROR rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) { int pos; UINT16 i; @@ -80,48 +82,61 @@ BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); Stream_SetPosition(s, 0); - return status; + return status ? CHANNEL_RC_OK: ERROR_INTERNAL_ERROR; } -static BOOL rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s) +static WIN32ERROR rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s) { UINT16 timestamp; BYTE confirmBlockNum; + WIN32ERROR error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 4) - return FALSE; + { + WLog_ERR(TAG, "not enought data in stream!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT16(s, timestamp); Stream_Read_UINT8(s, confirmBlockNum); Stream_Seek_UINT8(s); - IFCALL(context->ConfirmBlock, context, confirmBlockNum, timestamp); + IFCALLRET(context->ConfirmBlock, error, context, confirmBlockNum, timestamp); + if (error) + WLog_ERR(TAG, "context->ConfirmBlock failed with error %lu", error); - return TRUE; + return error; } -static BOOL rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s) +static WIN32ERROR rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s) { UINT16 quality; if (Stream_GetRemainingLength(s) < 4) - return FALSE; + { + WLog_ERR(TAG, "not enought data in stream!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT16(s, quality); Stream_Seek_UINT16(s); // reserved - WLog_ERR(TAG, "Client requested sound quality: %#0X", quality); - return TRUE; + WLog_DBG(TAG, "Client requested sound quality: %#0X", quality); + return CHANNEL_RC_OK; } -static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) +static WIN32ERROR rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) { int i, num_known_format = 0; UINT32 flags, vol, pitch; UINT16 udpPort; BYTE lastblock; + WIN32ERROR error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 20) - return FALSE; + { + WLog_ERR(TAG, "not enought data in stream!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, flags); /* dwFlags */ Stream_Read_UINT32(s, vol); /* dwVolume */ @@ -134,22 +149,33 @@ static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) /* this check is only a guess as cbSize can influence the size of a format record */ if (Stream_GetRemainingLength(s) < context->num_client_formats * 18) - return FALSE; + { + WLog_ERR(TAG, "not enought data in stream!"); + return ERROR_INVALID_DATA; + } if (!context->num_client_formats) { WLog_ERR(TAG, "client doesn't support any format!"); - return FALSE; + return ERROR_INTERNAL_ERROR; } context->client_formats = (AUDIO_FORMAT *)calloc(context->num_client_formats, sizeof(AUDIO_FORMAT)); if (!context->client_formats) - return FALSE; + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } for (i = 0; i < context->num_client_formats; i++) { if (Stream_GetRemainingLength(s) < 18) + { + WLog_ERR(TAG, "not enought data in stream!"); + error = ERROR_INVALID_DATA; goto out_free; + } + Stream_Read_UINT16(s, context->client_formats[i].wFormatTag); Stream_Read_UINT16(s, context->client_formats[i].nChannels); @@ -162,7 +188,12 @@ static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) if (context->client_formats[i].cbSize > 0) { if (!Stream_SafeSeek(s, context->client_formats[i].cbSize)) + { + WLog_ERR(TAG, "Stream_SafeSeek failed!"); + error = ERROR_INTERNAL_ERROR; goto out_free; + } + } if (context->client_formats[i].wFormatTag != 0) @@ -179,11 +210,11 @@ static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) goto out_free; } - return TRUE; + return CHANNEL_RC_OK; out_free: free(context->client_formats); - return FALSE; + return error; } static void* rdpsnd_server_thread(void* arg) @@ -191,39 +222,47 @@ static void* rdpsnd_server_thread(void* arg) DWORD nCount, status; HANDLE events[8]; RdpsndServerContext* context; - BOOL doRun; + WIN32ERROR error = CHANNEL_RC_OK; context = (RdpsndServerContext *)arg; nCount = 0; events[nCount++] = context->priv->channelEvent; events[nCount++] = context->priv->StopEvent; - if (!rdpsnd_server_send_formats(context, context->priv->rdpsnd_pdu)) + if ((error = rdpsnd_server_send_formats(context, context->priv->rdpsnd_pdu))) + { + WLog_ERR(TAG, "rdpsnd_server_send_formats failed with error %lu", error); goto out; + } - doRun = TRUE; - while (doRun) + while (TRUE) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) break; - if (rdpsnd_server_handle_messages(context) == 0) + if ((error = rdpsnd_server_handle_messages(context))) + { + WLog_ERR(TAG, "rdpsnd_server_handle_messages failed with error %lu", error); break; + } } out: + if (error && context->rdpcontext) + setChannelError(context->rdpcontext, error, "rdpsnd_server_thread reported an error"); + ExitThread((DWORD)error); return NULL; } -static BOOL rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread) +static WIN32ERROR rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread) { context->priv->ownThread = ownThread; - return context->Start(context) >= 0; + return context->Start(context); } -static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index) +static WIN32ERROR rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index) { int bs; int out_buffer_size; @@ -232,7 +271,7 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client if (client_format_index < 0 || client_format_index >= context->num_client_formats) { WLog_ERR(TAG, "index %d is not correct.", client_format_index); - return FALSE; + return ERROR_INVALID_DATA; } context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8; @@ -244,7 +283,7 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client if (format->nSamplesPerSec == 0) { WLog_ERR(TAG, "invalid Client Sound Format!!"); - return FALSE; + return ERROR_INVALID_DATA; } switch(format->wFormatTag) @@ -277,17 +316,20 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client newBuffer = (BYTE *)realloc(context->priv->out_buffer, out_buffer_size); if (!newBuffer) - return FALSE; + { + WLog_ERR(TAG, "realloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } context->priv->out_buffer = newBuffer; context->priv->out_buffer_size = out_buffer_size; } freerdp_dsp_context_reset_adpcm(context->priv->dsp_context); - return TRUE; + return CHANNEL_RC_OK; } -static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp) +static WIN32ERROR rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp) { int size; BYTE* src; @@ -298,6 +340,7 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT int tbytes_per_frame; ULONG written; wStream* s = context->priv->rdpsnd_pdu; + WIN32ERROR error = CHANNEL_RC_OK; format = &context->client_formats[context->selected_client_format]; tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample; @@ -360,13 +403,19 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); if (!status) + { + WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); + error = ERROR_INTERNAL_ERROR; goto out; + } + Stream_SetPosition(s, 0); /* Wave PDU */ if (!Stream_EnsureRemainingCapacity(s, size + fill_size)) { - status = -1; + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + error = CHANNEL_RC_NO_MEMORY; goto out; } Stream_Write_UINT32(s, 0); /* bPad */ @@ -377,19 +426,26 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); + if (!status) + { + WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); + error = ERROR_INTERNAL_ERROR; + } + out: Stream_SetPosition(s, 0); context->priv->out_pending_frames = 0; - return status; + return error; } -static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp) +static WIN32ERROR rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp) { int cframes; int cframesize; + WIN32ERROR error = CHANNEL_RC_OK; if (context->selected_client_format < 0) - return FALSE; + return ERROR_INVALID_DATA; while (nframes > 0) { @@ -404,15 +460,16 @@ static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* if (context->priv->out_pending_frames >= context->priv->out_frames) { - if (!rdpsnd_server_send_audio_pdu(context, wTimestamp)) - return FALSE; + if ((error = rdpsnd_server_send_audio_pdu(context, wTimestamp))) + WLog_ERR(TAG, "rdpsnd_server_send_audio_pdu failed with error %lu", error); + } } - return TRUE; + return error; } -static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right) +static WIN32ERROR rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right) { int pos; BOOL status; @@ -433,23 +490,27 @@ static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); Stream_SetPosition(s, 0); - return status; + return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } -static BOOL rdpsnd_server_close(RdpsndServerContext* context) +static WIN32ERROR rdpsnd_server_close(RdpsndServerContext* context) { int pos; BOOL status; ULONG written; wStream* s = context->priv->rdpsnd_pdu; + WIN32ERROR error = CHANNEL_RC_OK; if (context->selected_client_format < 0) - return FALSE; + return ERROR_INVALID_DATA; if (context->priv->out_pending_frames > 0) { - if (!rdpsnd_server_send_audio_pdu(context, 0)) - return FALSE; + if ((error = rdpsnd_server_send_audio_pdu(context, 0))) + { + WLog_ERR(TAG, "rdpsnd_server_send_audio_pdu failed with error %lu", error); + return error; + } } context->selected_client_format = -1; @@ -465,18 +526,22 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context) status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); Stream_SetPosition(s, 0); - return status; + return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } -static int rdpsnd_server_start(RdpsndServerContext* context) +static WIN32ERROR rdpsnd_server_start(RdpsndServerContext* context) { void *buffer = NULL; DWORD bytesReturned; RdpsndServerPrivate *priv = context->priv; + WIN32ERROR error = ERROR_INTERNAL_ERROR; priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd"); if (!priv->ChannelHandle) - return -1; + { + WLog_ERR(TAG, "WTSVirtualChannelOpen failed!"); + return ERROR_INTERNAL_ERROR; + } if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE))) { @@ -492,22 +557,32 @@ static int rdpsnd_server_start(RdpsndServerContext* context) priv->rdpsnd_pdu = Stream_New(NULL, 4096); if (!priv->rdpsnd_pdu) + { + WLog_ERR(TAG, "Stream_New failed!"); + error = CHANNEL_RC_NO_MEMORY; goto out_close; - + } if (priv->ownThread) { context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!context->priv->StopEvent) + { + WLog_ERR(TAG, "CreateEvent failed!"); goto out_pdu; + } context->priv->Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL); if (!context->priv->Thread) + { + WLog_ERR(TAG, "CreateThread failed!"); goto out_stopEvent; + } + } - return 0; + return CHANNEL_RC_OK; out_stopEvent: CloseHandle(context->priv->StopEvent); @@ -518,10 +593,10 @@ out_pdu: out_close: WTSVirtualChannelClose(context->priv->ChannelHandle); context->priv->ChannelHandle = NULL; - return -1; + return error; } -static int rdpsnd_server_stop(RdpsndServerContext* context) +static WIN32ERROR rdpsnd_server_stop(RdpsndServerContext* context) { if (context->priv->ownThread) { @@ -538,7 +613,7 @@ static int rdpsnd_server_stop(RdpsndServerContext* context) if (context->priv->rdpsnd_pdu) Stream_Free(context->priv->rdpsnd_pdu, TRUE); - return 0; + return CHANNEL_RC_OK; } RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm) @@ -548,7 +623,10 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm) context = (RdpsndServerContext *)calloc(1, sizeof(RdpsndServerContext)); if (!context) + { + WLog_ERR(TAG, "calloc failed!"); return NULL; + } context->vcm = vcm; @@ -564,15 +642,24 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm) context->priv = priv = (RdpsndServerPrivate *)calloc(1, sizeof(RdpsndServerPrivate)); if (!priv) + { + WLog_ERR(TAG, "calloc failed!"); goto out_free; + } priv->dsp_context = freerdp_dsp_context_new(); if (!priv->dsp_context) + { + WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); goto out_free_priv; + } priv->input_stream = Stream_New(NULL, 4); if (!priv->input_stream) + { + WLog_ERR(TAG, "Stream_New failed!"); goto out_free_dsp; + } priv->expectedBytes = 4; priv->waitingHeader = TRUE; @@ -625,14 +712,13 @@ HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context) * * @param Server side context * - * @return -1 if no data could be read, - * 0 on error (like connection close), - * 1 on succsess (also if further bytes need to be read) + * @return 0 on success + * otherwise error */ -int rdpsnd_server_handle_messages(RdpsndServerContext *context) +WIN32ERROR rdpsnd_server_handle_messages(RdpsndServerContext *context) { DWORD bytesReturned; - BOOL ret; + WIN32ERROR ret = CHANNEL_RC_OK; RdpsndServerPrivate *priv = context->priv; wStream *s = priv->input_stream; @@ -640,16 +726,16 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context) if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) - return -1; + return CHANNEL_RC_OK; WLog_ERR(TAG, "channel connection closed"); - return 0; + return ERROR_INTERNAL_ERROR; } priv->expectedBytes -= bytesReturned; Stream_Seek(s, bytesReturned); if (priv->expectedBytes) - return 1; + return CHANNEL_RC_OK; Stream_SealLength(s); Stream_SetPosition(s, 0); @@ -665,8 +751,11 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context) if (priv->expectedBytes) { if (!Stream_EnsureCapacity(s, priv->expectedBytes)) - return 0; - return 1; + { + WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); + return CHANNEL_RC_NO_MEMORY; + } + return CHANNEL_RC_OK; } } @@ -686,7 +775,7 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context) case SNDC_FORMATS: ret = rdpsnd_server_recv_formats(context, s); - if (ret && context->clientVersion < 6) + if ((ret == CHANNEL_RC_OK) && (context->clientVersion < 6)) IFCALL(context->Activated, context); break; @@ -695,19 +784,16 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context) ret = rdpsnd_server_recv_quality_mode(context, s); Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */ - if (ret && context->clientVersion >= 6) + if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= 6)) IFCALL(context->Activated, context); break; default: WLog_ERR(TAG, "UNKOWN MESSAGE TYPE!! (%#0X)", priv->msgType); - ret = FALSE; + ret = ERROR_INVALID_DATA; break; } Stream_SetPosition(s, 0); - if (ret) - return 1; - else - return 0; + return ret; } diff --git a/channels/remdesk/client/remdesk_main.c b/channels/remdesk/client/remdesk_main.c index c23f212..4f37077 100644 --- a/channels/remdesk/client/remdesk_main.c +++ b/channels/remdesk/client/remdesk_main.c @@ -589,7 +589,7 @@ static WIN32ERROR remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDE static WIN32ERROR remdesk_process_receive(remdeskPlugin* remdesk, wStream* s) { - WIN32ERROR status = CHANNEL_RC_OK; + WIN32ERROR status; REMDESK_CHANNEL_HEADER header; #if 0 @@ -775,7 +775,11 @@ static WIN32ERROR remdesk_virtual_channel_event_data_received(remdeskPlugin* rem Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - MessageQueue_Post(remdesk->queue, NULL, 0, (void*) data_in, NULL); + if (!MessageQueue_Post(remdesk->queue, NULL, 0, (void*) data_in, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } } return CHANNEL_RC_OK; } @@ -784,23 +788,21 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { remdeskPlugin* remdesk; + WIN32ERROR error; remdesk = (remdeskPlugin*) remdesk_get_open_handle_data(openHandle); if (!remdesk) { WLog_ERR(TAG, "error no match"); - remdesk->error = CHANNEL_RC_BAD_CHANNEL; - //TODO report error return; } - remdesk->error = CHANNEL_RC_OK; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - if ((remdesk->error = remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags))) - WLog_ERR(TAG, "remdesk_virtual_channel_event_data_received failed with error %lu!", remdesk->error); + if ((error = remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "remdesk_virtual_channel_event_data_received failed with error %lu!", error); break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -810,7 +812,9 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT case CHANNEL_EVENT_USER: break; } - //TODO report error + if (error && remdesk->rdpcontext) + setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_open_event reported an error"); + } static void* remdesk_virtual_channel_client_thread(void* arg) @@ -825,25 +829,34 @@ static void* remdesk_virtual_channel_client_thread(void* arg) while (1) { if (!MessageQueue_Wait(remdesk->queue)) + { + WLog_ERR(TAG, "MessageQueue_Wait failed!"); + error = ERROR_INTERNAL_ERROR; break; + } - if (MessageQueue_Peek(remdesk->queue, &message, TRUE)) - { - if (message.id == WMQ_QUIT) - break; + if (!MessageQueue_Peek(remdesk->queue, &message, TRUE)) { + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; + break; + } + if (message.id == WMQ_QUIT) + break; - if (message.id == 0) + if (message.id == 0) + { + data = (wStream*) message.wParam; + if ((error = remdesk_process_receive(remdesk, data))) { - data = (wStream*) message.wParam; - if ((error = remdesk_process_receive(remdesk, data))) - { - WLog_ERR(TAG, "remdesk_process_receive failed with error %lu!", error); - break; - } + WLog_ERR(TAG, "remdesk_process_receive failed with error %lu!", error); + break; } } } + if (error && remdesk->rdpcontext) + setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_client_thread reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -933,36 +946,34 @@ static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk) static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { remdeskPlugin* remdesk; + WIN32ERROR error = CHANNEL_RC_OK; remdesk = (remdeskPlugin*) remdesk_get_init_handle_data(pInitHandle); if (!remdesk) { WLog_ERR(TAG, "error no match"); - remdesk->error = CHANNEL_RC_BAD_CHANNEL; - //TODO report error return; } - remdesk->error = CHANNEL_RC_OK; - switch (event) { case CHANNEL_EVENT_CONNECTED: - if ((remdesk->error = remdesk_virtual_channel_event_connected(remdesk, pData, dataLength))) - WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu", remdesk->error); + if ((error = remdesk_virtual_channel_event_connected(remdesk, pData, dataLength))) + WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu", error); break; case CHANNEL_EVENT_DISCONNECTED: - if ((remdesk->error = remdesk_virtual_channel_event_disconnected(remdesk))) - WLog_ERR(TAG, "remdesk_virtual_channel_event_disconnected failed with error %lu", remdesk->error); + if ((error = remdesk_virtual_channel_event_disconnected(remdesk))) + WLog_ERR(TAG, "remdesk_virtual_channel_event_disconnected failed with error %lu", error); break; case CHANNEL_EVENT_TERMINATED: remdesk_virtual_channel_event_terminated(remdesk); break; } - //TODO report error + if (error && remdesk->rdpcontext) + setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_init_event reported an error"); } /* remdesk is always built-in */ @@ -1011,6 +1022,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) *(pEntryPointsEx->ppInterface) = (void*) context; remdesk->context = context; + remdesk->rdpcontext = pEntryPointsEx->context; } CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); diff --git a/channels/remdesk/client/remdesk_main.h b/channels/remdesk/client/remdesk_main.h index 743da6c..59e92ca 100644 --- a/channels/remdesk/client/remdesk_main.h +++ b/channels/remdesk/client/remdesk_main.h @@ -56,7 +56,7 @@ struct remdesk_plugin char* ExpertBlob; BYTE* EncryptedPassStub; int EncryptedPassStubSize; - WIN32ERROR error; + rdpContext* rdpcontext; }; typedef struct remdesk_plugin remdeskPlugin; diff --git a/channels/remdesk/server/remdesk_main.c b/channels/remdesk/server/remdesk_main.c index 9c18c86..1b3b490 100644 --- a/channels/remdesk/server/remdesk_main.c +++ b/channels/remdesk/server/remdesk_main.c @@ -543,8 +543,8 @@ static void* remdesk_server_thread(void* arg) if (!s) { WLog_ERR(TAG, "Stream_New failed!"); - ExitThread(CHANNEL_RC_NO_MEMORY); - return NULL; + error = CHANNEL_RC_NO_MEMORY; + goto out; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) @@ -557,8 +557,8 @@ static void* remdesk_server_thread(void* arg) else { WLog_ERR(TAG, "WTSVirtualChannelQuery failed!"); - ExitThread(ERROR_INTERNAL_ERROR); - return NULL; + error = ERROR_INTERNAL_ERROR; + goto out; } nCount = 0; @@ -568,8 +568,7 @@ static void* remdesk_server_thread(void* arg) if ((error = remdesk_send_ctl_version_info_pdu(context))) { WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu!", error); - ExitThread((DWORD)error); - return NULL; + goto out; } while (1) @@ -617,7 +616,10 @@ static void* remdesk_server_thread(void* arg) } Stream_Free(s, TRUE); - //TODO signal error +out: + if (error && context->rdpcontext) + setChannelError(context->rdpcontext, error, "remdesk_server_thread reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -638,7 +640,6 @@ static WIN32ERROR remdesk_server_start(RemdeskServerContext* context) return ERROR_INTERNAL_ERROR; } - //TODO implement error reporting if (!(context->priv->Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL))) { diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index 620e10f..52c0081 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -68,6 +68,7 @@ struct _SERIAL_DEVICE wListDictionary *IrpThreads; UINT32 IrpThreadToBeTerminatedCount; CRITICAL_SECTION TerminatingIrpThreadsLock; + rdpContext* rdpcontext; }; typedef struct _IRP_THREAD_DATA IRP_THREAD_DATA; @@ -454,22 +455,29 @@ static void* irp_thread_func(void* arg) /* blocks until the end of the request */ if ((error = serial_process_irp(data->serial, data->irp))) + { WLog_ERR(TAG, "serial_process_irp failed with error %lu", error); + goto error_out; + } EnterCriticalSection(&data->serial->TerminatingIrpThreadsLock); data->serial->IrpThreadToBeTerminatedCount++; - data->irp->Complete(data->irp); + error = data->irp->Complete(data->irp); LeaveCriticalSection(&data->serial->TerminatingIrpThreadsLock); +error_out: + if (error && data->serial->rdpcontext) + setChannelError(data->serial->rdpcontext, error, "irp_thread_func reported an error"); + /* NB: At this point, the server might already being reusing * the CompletionId whereas the thread is not yet * terminated */ free(data); - ExitThread(0); + ExitThread((DWORD)error); return NULL; } @@ -477,7 +485,7 @@ static void* irp_thread_func(void* arg) static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp) { IRP_THREAD_DATA *data = NULL; - HANDLE irpThread = INVALID_HANDLE_VALUE; + HANDLE irpThread; HANDLE previousIrpThread; uintptr_t key; @@ -630,7 +638,11 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp) key = irp->CompletionId; - ListDictionary_Add(serial->IrpThreads, (void*)key, irpThread); + if (!ListDictionary_Add(serial->IrpThreads, (void*)key, irpThread)) + { + WLog_ERR(TAG, "ListDictionary_Add failed!"); + goto error_handle; + } return; @@ -677,14 +689,23 @@ static void* serial_thread_func(void* arg) IRP* irp; wMessage message; SERIAL_DEVICE* serial = (SERIAL_DEVICE*) arg; + WIN32ERROR error = CHANNEL_RC_OK; while (1) { if (!MessageQueue_Wait(serial->MainIrpQueue)) + { + WLog_ERR(TAG, "MessageQueue_Wait failed!"); + error = ERROR_INTERNAL_ERROR; break; + } if (!MessageQueue_Peek(serial->MainIrpQueue, &message, TRUE)) + { + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; break; + } if (message.id == WMQ_QUIT) { @@ -698,7 +719,10 @@ static void* serial_thread_func(void* arg) create_irp_thread(serial, irp); } - ExitThread(0); + if (error && serial->rdpcontext) + setChannelError(serial->rdpcontext, error, "serial_thread_func reported an error"); + + ExitThread((DWORD) error); return NULL; } @@ -717,7 +741,11 @@ static WIN32ERROR serial_irp_request(DEVICE* device, IRP* irp) * write requests. */ - MessageQueue_Post(serial->MainIrpQueue, NULL, 0, (void*) irp, NULL); + if (!MessageQueue_Post(serial->MainIrpQueue, NULL, 0, (void*) irp, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } return CHANNEL_RC_OK; } @@ -809,6 +837,7 @@ WIN32ERROR DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) serial->device.name = name; serial->device.IRPRequest = serial_irp_request; serial->device.Free = serial_free; + serial->rdpcontext = pEntryPoints->rdpcontext; len = strlen(name); serial->device.data = Stream_New(NULL, len + 1); diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c index 9043184..b0b5654 100644 --- a/channels/smartcard/client/smartcard_main.c +++ b/channels/smartcard/client/smartcard_main.c @@ -41,6 +41,7 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext) wMessage message; SMARTCARD_DEVICE* smartcard; SMARTCARD_OPERATION* operation; + WIN32ERROR error = CHANNEL_RC_OK; smartcard = pContext->smartcard; @@ -54,7 +55,12 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext) if (WaitForSingleObject(MessageQueue_Event(pContext->IrpQueue), 0) == WAIT_OBJECT_0) { if (!MessageQueue_Peek(pContext->IrpQueue, &message, TRUE)) + { + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + status = ERROR_INTERNAL_ERROR; break; + } + if (message.id == WMQ_QUIT) break; @@ -69,14 +75,23 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext) break; } - Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) operation->irp); + if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) operation->irp)) + { + WLog_ERR(TAG, "Queue_Enqueue failed!"); + status = ERROR_INTERNAL_ERROR; + break; + + } free(operation); } } } - ExitThread(0); + if (status && smartcard->rdpcontext) + setChannelError(smartcard->rdpcontext, error, "smartcard_context_thread reported an error"); + + ExitThread((DWORD)status); return NULL; } @@ -86,20 +101,30 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTE pContext = (SMARTCARD_CONTEXT*) calloc(1, sizeof(SMARTCARD_CONTEXT)); if (!pContext) + { + WLog_ERR(TAG, "calloc failed!"); return pContext; + } pContext->smartcard = smartcard; pContext->hContext = hContext; pContext->IrpQueue = MessageQueue_New(NULL); if (!pContext->IrpQueue) + { + WLog_ERR(TAG, "MessageQueue_New failed!"); goto error_irpqueue; + } pContext->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_context_thread, pContext, 0, NULL); if (!pContext->thread) + { + WLog_ERR(TAG, "CreateThread failed!"); goto error_thread; + } + return pContext; error_thread: @@ -248,29 +273,6 @@ WIN32ERROR smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) return irp->Complete(irp); } -void* smartcard_process_irp_worker_proc(SMARTCARD_OPERATION* operation) -{ - IRP* irp; - LONG status; - SMARTCARD_DEVICE* smartcard; - - irp = operation->irp; - smartcard = (SMARTCARD_DEVICE*) irp->device; - - if ((status = smartcard_irp_device_control_call(smartcard, operation))) - { - WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu", status); - //TODO report error - } - - Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp); - - free(operation); - - ExitThread(0); - return NULL; -} - /** * Multiple threads and SCardGetStatusChange: * http://musclecard.996296.n3.nabble.com/Multiple-threads-and-SCardGetStatusChange-td4430.html @@ -456,7 +458,12 @@ static void* smartcard_thread_func(void* arg) if (WaitForSingleObject(MessageQueue_Event(smartcard->IrpQueue), 0) == WAIT_OBJECT_0) { if (!MessageQueue_Peek(smartcard->IrpQueue, &message, TRUE)) + { + WLog_ERR(TAG, "MessageQueue_Peek failed!"); + error = ERROR_INTERNAL_ERROR; break; + } + if (message.id == WMQ_QUIT) { @@ -518,7 +525,9 @@ static void* smartcard_thread_func(void* arg) } } out: - //TODO signal error + if (error && smartcard->rdpcontext) + setChannelError(smartcard->rdpcontext, error, "smartcard_thread_func reported an error"); + ExitThread((DWORD)error); return NULL; } @@ -526,7 +535,11 @@ out: static WIN32ERROR smartcard_irp_request(DEVICE* device, IRP* irp) { SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; - MessageQueue_Post(smartcard->IrpQueue, NULL, 0, (void*) irp, NULL); + if (!MessageQueue_Post(smartcard->IrpQueue, NULL, 0, (void*) irp, NULL)) + { + WLog_ERR(TAG, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } return CHANNEL_RC_OK; } @@ -560,6 +573,7 @@ WIN32ERROR DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) smartcard->device.IRPRequest = smartcard_irp_request; smartcard->device.Init = smartcard_init; smartcard->device.Free = smartcard_free; + smartcard->rdpcontext = pEntryPoints->rdpcontext; length = strlen(smartcard->device.name); smartcard->device.data = Stream_New(NULL, length + 1); diff --git a/channels/smartcard/client/smartcard_main.h b/channels/smartcard/client/smartcard_main.h index 09017df..96d925c 100644 --- a/channels/smartcard/client/smartcard_main.h +++ b/channels/smartcard/client/smartcard_main.h @@ -119,6 +119,7 @@ struct _SMARTCARD_DEVICE wQueue* CompletedIrpQueue; wListDictionary* rgSCardContextList; wListDictionary* rgOutstandingMessages; + rdpContext* rdpcontext; }; SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTEXT hContext); diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c index 93bd1a7..ee6c55b 100644 --- a/channels/tsmf/client/tsmf_ifman.c +++ b/channels/tsmf/client/tsmf_ifman.c @@ -4,6 +4,8 @@ * * Copyright 2010-2011 Vic Lee * Copyright 2012 Hewlett-Packard Development Company, L.P. + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -180,7 +182,7 @@ WIN32ERROR tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman) return status; } -WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman, rdpContext* rdpcontext) { UINT32 StreamId; WIN32ERROR status = CHANNEL_RC_OK; @@ -203,7 +205,7 @@ WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman) { Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numMediaType */ - stream = tsmf_stream_new(presentation, StreamId); + stream = tsmf_stream_new(presentation, StreamId, rdpcontext); if (!stream) return ERROR_OUTOFMEMORY; diff --git a/channels/tsmf/client/tsmf_ifman.h b/channels/tsmf/client/tsmf_ifman.h index c5e2cb8..056d4db 100644 --- a/channels/tsmf/client/tsmf_ifman.h +++ b/channels/tsmf/client/tsmf_ifman.h @@ -3,6 +3,8 @@ * Video Redirection Virtual Channel - Interface Manipulation * * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +22,8 @@ #ifndef __TSMF_IFMAN_H #define __TSMF_IFMAN_H +#include + typedef struct _TSMF_IFMAN TSMF_IFMAN; struct _TSMF_IFMAN { @@ -42,7 +46,7 @@ WIN32ERROR tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman); WIN32ERROR tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman); WIN32ERROR tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman); WIN32ERROR tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman); -WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman, rdpContext* rdpcontext); WIN32ERROR tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman); WIN32ERROR tsmf_ifman_remove_stream(TSMF_IFMAN* ifman); WIN32ERROR tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman); diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index 930f1a1..648774a 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -3,6 +3,8 @@ * Video Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -170,7 +172,7 @@ static WIN32ERROR tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCall processed = TRUE; break; case ADD_STREAM: - error = tsmf_ifman_add_stream(&ifman); + error = tsmf_ifman_add_stream(&ifman, ((TSMF_PLUGIN*) callback->plugin)->rdpcontext); processed = TRUE; break; case SET_TOPOLOGY_REQ: @@ -461,7 +463,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) WIN32ERROR status = 0; TSMF_PLUGIN* tsmf; TsmfClientContext* context; - WIN32ERROR error = ERROR_OUTOFMEMORY; + WIN32ERROR error = CHANNEL_RC_NO_MEMORY; tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf"); @@ -469,16 +471,25 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { tsmf = (TSMF_PLUGIN*) calloc(1, sizeof(TSMF_PLUGIN)); if (!tsmf) - return ERROR_OUTOFMEMORY; + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + tsmf->iface.Initialize = tsmf_plugin_initialize; tsmf->iface.Connected = NULL; tsmf->iface.Disconnected = NULL; tsmf->iface.Terminated = tsmf_plugin_terminated; + tsmf->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context; context = (TsmfClientContext*) calloc(1, sizeof(TsmfClientContext)); if (!context) + { + WLog_ERR(TAG, "calloc failed!"); goto error_context; + } + context->handle = (void*) tsmf; tsmf->iface.pInterface = (void*) context; @@ -492,7 +503,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf); } - if (status == 0) + if (status == CHANNEL_RC_OK) { status = tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints)); } diff --git a/channels/tsmf/client/tsmf_main.h b/channels/tsmf/client/tsmf_main.h index 04f8f4c..e29a00a 100644 --- a/channels/tsmf/client/tsmf_main.h +++ b/channels/tsmf/client/tsmf_main.h @@ -3,6 +3,8 @@ * Video Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +22,8 @@ #ifndef __TSMF_MAIN_H #define __TSMF_MAIN_H +#include + typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK; typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK; @@ -56,6 +60,8 @@ struct _TSMF_PLUGIN const char* decoder_name; const char* audio_name; const char* audio_device; + + rdpContext* rdpcontext; }; BOOL tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback, diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c index 6ab2d73..f6e045f 100644 --- a/channels/tsmf/client/tsmf_media.c +++ b/channels/tsmf/client/tsmf_media.c @@ -4,6 +4,8 @@ * * Copyright 2010-2011 Vic Lee * Copyright 2012 Hewlett-Packard Development Company, L.P. + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -110,6 +112,7 @@ struct _TSMF_STREAM wQueue *sample_list; wQueue *sample_ack_list; + rdpContext* rdpcontext; }; struct _TSMF_SAMPLE @@ -596,6 +599,7 @@ static void* tsmf_stream_ack_func(void *arg) { HANDLE hdl[2]; TSMF_STREAM* stream = (TSMF_STREAM*) arg; + WIN32ERROR error = CHANNEL_RC_OK; DEBUG_TSMF("in %d", stream->stream_id); hdl[0] = stream->stopEvent; @@ -615,9 +619,17 @@ static void* tsmf_stream_ack_func(void *arg) continue; if (tsmf_stream_process_ack(stream, FALSE)) + { + error = ERROR_INTERNAL_ERROR; + WLog_ERR(TAG, "tsmf_stream_process_ack failed!"); break; + } + } + if (error && stream->rdpcontext) + setChannelError(stream->rdpcontext, error, "tsmf_stream_ack_func reported an error"); + DEBUG_TSMF("out %d", stream->stream_id); ExitThread(0); return NULL; @@ -629,6 +641,7 @@ static void* tsmf_stream_playback_func(void *arg) TSMF_SAMPLE* sample; TSMF_STREAM* stream = (TSMF_STREAM *) arg; TSMF_PRESENTATION* presentation = stream->presentation; + WIN32ERROR error = CHANNEL_RC_OK; DEBUG_TSMF("in %d", stream->stream_id); @@ -661,6 +674,7 @@ static void* tsmf_stream_playback_func(void *arg) if (sample && !tsmf_sample_playback(sample)) { WLog_ERR(TAG, "error playing sample"); + error = ERROR_INTERNAL_ERROR; break; } } @@ -671,6 +685,9 @@ static void* tsmf_stream_playback_func(void *arg) stream->audio = NULL; } + if (error && stream->rdpcontext) + setChannelError(stream->rdpcontext, error, "tsmf_stream_playback_func reported an error"); + DEBUG_TSMF("out %d", stream->stream_id); ExitThread(0); return NULL; @@ -972,7 +989,7 @@ void tsmf_presentation_free(TSMF_PRESENTATION* presentation) ArrayList_Remove(presentation_list, presentation); } -TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id) +TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id, rdpContext* rdpcontext) { TSMF_STREAM* stream; stream = tsmf_stream_find_by_id(presentation, stream_id); @@ -1017,6 +1034,8 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id) if (ArrayList_Add(presentation->stream_list, stream) < 0) goto error_add; + stream->rdpcontext = rdpcontext; + return stream; error_add: diff --git a/channels/tsmf/client/tsmf_media.h b/channels/tsmf/client/tsmf_media.h index f26f16a..4ed51f8 100644 --- a/channels/tsmf/client/tsmf_media.h +++ b/channels/tsmf/client/tsmf_media.h @@ -4,6 +4,8 @@ * * Copyright 2010-2011 Vic Lee * Copyright 2012 Hewlett-Packard Development Company, L.P. + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +28,8 @@ #ifndef __TSMF_MEDIA_H #define __TSMF_MEDIA_H +#include + typedef struct _TSMF_PRESENTATION TSMF_PRESENTATION; typedef struct _TSMF_STREAM TSMF_STREAM; @@ -48,7 +52,7 @@ void tsmf_presentation_set_audio_device(TSMF_PRESENTATION *presentation, BOOL tsmf_presentation_flush(TSMF_PRESENTATION *presentation); void tsmf_presentation_free(TSMF_PRESENTATION *presentation); -TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id); +TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id, rdpContext* rdpcontext); TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stream_id); BOOL tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s); void tsmf_stream_end(TSMF_STREAM *stream); diff --git a/include/freerdp/channels/rdpdr.h b/include/freerdp/channels/rdpdr.h index 7ada8cb..cc3c412 100644 --- a/include/freerdp/channels/rdpdr.h +++ b/include/freerdp/channels/rdpdr.h @@ -373,10 +373,11 @@ struct _DEVICE_SERVICE_ENTRY_POINTS pcRegisterDevice RegisterDevice; RDPDR_DEVICE* device; + rdpContext* rdpcontext; }; typedef struct _DEVICE_SERVICE_ENTRY_POINTS DEVICE_SERVICE_ENTRY_POINTS; typedef DEVICE_SERVICE_ENTRY_POINTS* PDEVICE_SERVICE_ENTRY_POINTS; -typedef int (*PDEVICE_SERVICE_ENTRY)(PDEVICE_SERVICE_ENTRY_POINTS); +typedef WIN32ERROR (*PDEVICE_SERVICE_ENTRY)(PDEVICE_SERVICE_ENTRY_POINTS); #endif /* FREERDP_CHANNEL_RDPDR_H */ diff --git a/include/freerdp/client/audin.h b/include/freerdp/client/audin.h index eff3196..6e2125c 100644 --- a/include/freerdp/client/audin.h +++ b/include/freerdp/client/audin.h @@ -23,6 +23,7 @@ #define FREERDP_CHANNEL_CLIENT_AUDIN_H #include +#include /** * Subsystem Interface @@ -61,6 +62,7 @@ struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS IWTSPlugin* plugin; PREGISTERAUDINDEVICE pRegisterAudinDevice; ADDIN_ARGV* args; + rdpContext* rdpcontext; }; typedef struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS FREERDP_AUDIN_DEVICE_ENTRY_POINTS; typedef FREERDP_AUDIN_DEVICE_ENTRY_POINTS* PFREERDP_AUDIN_DEVICE_ENTRY_POINTS; diff --git a/include/freerdp/client/cliprdr.h b/include/freerdp/client/cliprdr.h index 8fb2c95..f5576a0 100644 --- a/include/freerdp/client/cliprdr.h +++ b/include/freerdp/client/cliprdr.h @@ -27,6 +27,7 @@ #include #include +#include /** * Client Interface @@ -80,6 +81,8 @@ struct _cliprdr_client_context pcCliprdrServerFileContentsRequest ServerFileContentsRequest; pcCliprdrClientFileContentsResponse ClientFileContentsResponse; pcCliprdrServerFileContentsResponse ServerFileContentsResponse; + + rdpContext* rdpcontext; }; struct _CLIPRDR_FORMAT_NAME diff --git a/include/freerdp/client/rdpsnd.h b/include/freerdp/client/rdpsnd.h index 7e482ae..544b231 100644 --- a/include/freerdp/client/rdpsnd.h +++ b/include/freerdp/client/rdpsnd.h @@ -98,7 +98,7 @@ struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS typedef struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS FREERDP_RDPSND_DEVICE_ENTRY_POINTS; typedef FREERDP_RDPSND_DEVICE_ENTRY_POINTS* PFREERDP_RDPSND_DEVICE_ENTRY_POINTS; -typedef int (*PFREERDP_RDPSND_DEVICE_ENTRY)(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints); +typedef WIN32ERROR (*PFREERDP_RDPSND_DEVICE_ENTRY)(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints); #endif /* FREERDP_CHANNEL_CLIENT_RDPSND_H */ diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index 2df5e4c..6bb0ff4 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -3,8 +3,8 @@ * FreeRDP Interface * * Copyright 2009-2011 Jay Sorg - * Copyright 2014 DI (FH) Martin Haimberger - * + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -110,7 +110,11 @@ struct rdp_context ALIGN64 wPubSub* pubSub; /* (offset 18) */ - UINT64 paddingB[32 - 19]; /* 19 */ + ALIGN64 HANDLE channelErrorEvent; /* (offset 19)*/ + ALIGN64 WIN32ERROR channelErrorNum; /*(offset 20)*/ + ALIGN64 char* errorDescription; /*(offset 21)*/ + + UINT64 paddingB[32 - 22]; /* 22 */ ALIGN64 rdpRdp* rdp; /**< (offset 32) Pointer to a rdp_rdp structure used to keep the connection's parameters. @@ -280,6 +284,12 @@ FREERDP_API void freerdp_set_last_error(rdpContext* context, UINT32 lastError); FREERDP_API ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount); +FREERDP_API HANDLE getChannelErrorEventHandle(rdpContext* context); +FREERDP_API WIN32ERROR getChannelError(rdpContext* context); +FREERDP_API const char* getChannelErrorDescription(rdpContext* context); +FREERDP_API void setChannelError(rdpContext* context, WIN32ERROR errorNum, char* description); +FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context); + #ifdef __cplusplus } #endif diff --git a/include/freerdp/server/audin.h b/include/freerdp/server/audin.h index f935ac1..d441411 100644 --- a/include/freerdp/server/audin.h +++ b/include/freerdp/server/audin.h @@ -91,6 +91,8 @@ struct _audin_server_context * server must be careful of thread synchronization. */ psAudinServerReceiveSamples ReceiveSamples; + + rdpContext* rdpcontext; }; #ifdef __cplusplus diff --git a/include/freerdp/server/cliprdr.h b/include/freerdp/server/cliprdr.h index 5fbeb17..1477dc6 100644 --- a/include/freerdp/server/cliprdr.h +++ b/include/freerdp/server/cliprdr.h @@ -95,6 +95,8 @@ struct _cliprdr_server_context psCliprdrServerFileContentsRequest ServerFileContentsRequest; psCliprdrClientFileContentsResponse ClientFileContentsResponse; psCliprdrServerFileContentsResponse ServerFileContentsResponse; + + rdpContext* rdpcontext; }; #ifdef __cplusplus diff --git a/include/freerdp/server/echo.h b/include/freerdp/server/echo.h index ecd64c2..fbf21dc 100644 --- a/include/freerdp/server/echo.h +++ b/include/freerdp/server/echo.h @@ -72,6 +72,8 @@ struct _echo_server_context * Receive echo response PDU. */ psEchoServerResponse Response; + + rdpContext* rdpcontext; }; #ifdef __cplusplus diff --git a/include/freerdp/server/encomsp.h b/include/freerdp/server/encomsp.h index 678b360..dbc9e84 100644 --- a/include/freerdp/server/encomsp.h +++ b/include/freerdp/server/encomsp.h @@ -71,6 +71,8 @@ struct _encomsp_server_context psEncomspGraphicsStreamResumed GraphicsStreamResumed; EncomspServerPrivate* priv; + + rdpContext* rdpcontext; }; #ifdef __cplusplus diff --git a/include/freerdp/server/rdpdr.h b/include/freerdp/server/rdpdr.h index df65090..b980213 100644 --- a/include/freerdp/server/rdpdr.h +++ b/include/freerdp/server/rdpdr.h @@ -137,6 +137,8 @@ struct _rdpdr_server_context /*** Smartcard callbacks registered by the server. ***/ psRdpdrOnSmartcardCreate OnSmartcardCreate; psRdpdrOnSmartcardDelete OnSmartcardDelete; + + rdpContext* rdpcontext; }; #ifdef __cplusplus diff --git a/include/freerdp/server/rdpsnd.h b/include/freerdp/server/rdpsnd.h index 6aff908..a2e2fe8 100644 --- a/include/freerdp/server/rdpsnd.h +++ b/include/freerdp/server/rdpsnd.h @@ -3,6 +3,8 @@ * Server Audio Virtual Channel * * Copyright 2012 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,15 +29,15 @@ typedef struct _rdpsnd_server_context RdpsndServerContext; typedef struct _rdpsnd_server_context rdpsnd_server_context; typedef struct _rdpsnd_server_private RdpsndServerPrivate; -typedef int (*psRdpsndStart)(RdpsndServerContext* context); -typedef int (*psRdpsndStop)(RdpsndServerContext* context); +typedef WIN32ERROR (*psRdpsndStart)(RdpsndServerContext* context); +typedef WIN32ERROR (*psRdpsndStop)(RdpsndServerContext* context); -typedef BOOL (*psRdpsndServerInitialize)(RdpsndServerContext* context, BOOL ownThread); -typedef BOOL (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index); -typedef BOOL (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp); -typedef BOOL (*psRdpsndServerConfirmBlock)(RdpsndServerContext* context, BYTE confirmBlockNum, UINT16 wtimestamp); -typedef BOOL (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right); -typedef BOOL (*psRdpsndServerClose)(RdpsndServerContext* context); +typedef WIN32ERROR (*psRdpsndServerInitialize)(RdpsndServerContext* context, BOOL ownThread); +typedef WIN32ERROR (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index); +typedef WIN32ERROR (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp); +typedef WIN32ERROR (*psRdpsndServerConfirmBlock)(RdpsndServerContext* context, BYTE confirmBlockNum, UINT16 wtimestamp); +typedef WIN32ERROR (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right); +typedef WIN32ERROR (*psRdpsndServerClose)(RdpsndServerContext* context); typedef void (*psRdpsndServerActivated)(RdpsndServerContext* context); @@ -110,6 +112,8 @@ struct _rdpsnd_server_context * MS-RDPEA channel version the client announces */ UINT16 clientVersion; + + rdpContext* rdpcontext; }; #ifdef __cplusplus @@ -120,8 +124,8 @@ FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm); FREERDP_API void rdpsnd_server_context_reset(RdpsndServerContext *); FREERDP_API void rdpsnd_server_context_free(RdpsndServerContext* context); FREERDP_API HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context); -FREERDP_API int rdpsnd_server_handle_messages(RdpsndServerContext *context); -FREERDP_API BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s); +FREERDP_API WIN32ERROR rdpsnd_server_handle_messages(RdpsndServerContext *context); +FREERDP_API WIN32ERROR rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s); #ifdef __cplusplus diff --git a/include/freerdp/server/remdesk.h b/include/freerdp/server/remdesk.h index 6d61b2e..d442949 100644 --- a/include/freerdp/server/remdesk.h +++ b/include/freerdp/server/remdesk.h @@ -47,6 +47,7 @@ struct _remdesk_server_context psRemdeskStop Stop; RemdeskServerPrivate* priv; + rdpContext* rdpcontext; }; #ifdef __cplusplus diff --git a/include/freerdp/svc.h b/include/freerdp/svc.h index d424770..c6843cc 100644 --- a/include/freerdp/svc.h +++ b/include/freerdp/svc.h @@ -3,6 +3,8 @@ * Static Virtual Channel Interface * * Copyright 2009-2011 Jay Sorg + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +26,7 @@ #include #include +#include #define CHANNEL_EVENT_USER 1000 @@ -45,6 +48,7 @@ struct _CHANNEL_ENTRY_POINTS_FREERDP void* pExtendedData; /* extended initial data */ void* pInterface; /* channel callback interface, use after initialization */ void** ppInterface; /* channel callback interface, use for initialization */ + rdpContext* context; }; typedef struct _CHANNEL_ENTRY_POINTS_FREERDP CHANNEL_ENTRY_POINTS_FREERDP; typedef CHANNEL_ENTRY_POINTS_FREERDP* PCHANNEL_ENTRY_POINTS_FREERDP; diff --git a/libfreerdp/core/client.c b/libfreerdp/core/client.c index 2001feb..5bbe1df 100644 --- a/libfreerdp/core/client.c +++ b/libfreerdp/core/client.c @@ -3,6 +3,8 @@ * Client Channels * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -721,6 +723,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, P EntryPoints.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER; EntryPoints.ppInterface = &g_pInterface; EntryPoints.pExtendedData = data; + EntryPoints.context = ((freerdp*)settings->instance)->context; /* enable VirtualChannelInit */ channels->can_call_init = TRUE; diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index a220b9b..e1fa5cb 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -3,7 +3,8 @@ * FreeRDP Core * * Copyright 2011 Marc-Andre Moreau - * Copyright 2014 DI (FH) Martin Haimberger + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -229,8 +230,11 @@ DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count if (nCount == 0) return 0; - if (events && (nCount < count)) + if (events && (nCount < count + 1)) + { events[nCount++] = freerdp_channels_get_event_handle(context->instance); + events[nCount++] = getChannelErrorEventHandle(context); + } else return 0; @@ -248,6 +252,11 @@ BOOL freerdp_check_event_handles(rdpContext* context) status = freerdp_channels_check_fds(context->channels, context->instance); + if (!status) + return FALSE; + + status = checkChannelErrorEvent(context); + return status; } @@ -494,13 +503,28 @@ BOOL freerdp_context_new(freerdp* instance) instance->autodetect->context = context; + if (!(context->errorDescription = calloc(1, 500))) + { + WLog_ERR(TAG, "calloc failed!"); + goto out_error_description; + } + + if (!(context->channelErrorEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + goto out_error_create_event; + } + update_register_client_callbacks(rdp->update); IFCALLRET(instance->ContextNew, ret, instance, instance->context); if (ret) return TRUE; - +out_error_create_event: + CloseHandle(context->channelErrorEvent); +out_error_description: + free(context->errorDescription); out_error_graphics_new: rdp_free(rdp); out_error_rdp_new: @@ -540,8 +564,12 @@ void freerdp_context_free(freerdp* instance) metrics_free(instance->context->metrics); + CloseHandle(instance->context->channelErrorEvent); + free(instance->context->errorDescription); + free(instance->context); instance->context = NULL; + } UINT32 freerdp_error_info(freerdp* instance) @@ -706,3 +734,33 @@ FREERDP_API ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCoun context->rdp->transport->written = 0; return written; } + +FREERDP_API HANDLE getChannelErrorEventHandle(rdpContext* context) +{ + return context->channelErrorEvent; +} + +FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context) +{ + if (WaitForSingleObject( context->channelErrorEvent, 0) == WAIT_OBJECT_0) + { + WLog_ERR(TAG, "%s. Error was %lu", context->errorDescription, context->channelErrorNum); + return FALSE; + } + return TRUE; +} + +FREERDP_API WIN32ERROR getChannelError(rdpContext* context) +{ + return context->channelErrorNum; +} +FREERDP_API const char* getChannelErrorDescription(rdpContext* context) +{ + return context->errorDescription; +} +FREERDP_API void setChannelError(rdpContext* context, WIN32ERROR errorNum, char* description) +{ + context->channelErrorNum = errorNum; + strncpy(context->errorDescription, description, 499); + SetEvent(context->channelErrorEvent); +} diff --git a/server/Mac/mf_audin.c b/server/Mac/mf_audin.c index be96d2f..368a4b4 100644 --- a/server/Mac/mf_audin.c +++ b/server/Mac/mf_audin.c @@ -55,6 +55,7 @@ static WIN32ERROR mf_peer_audin_receive_samples(audin_server_context* context, c void mf_peer_audin_init(mfPeerContext* context) { context->audin = audin_server_context_new(context->vcm); + context->audin->rdpcontext = &context->_p; context->audin->data = context; context->audin->server_formats = supported_audio_formats; diff --git a/server/Mac/mf_rdpsnd.c b/server/Mac/mf_rdpsnd.c index 1580a43..b8c18a4 100644 --- a/server/Mac/mf_rdpsnd.c +++ b/server/Mac/mf_rdpsnd.c @@ -3,6 +3,8 @@ * FreeRDP Mac OS X Server (Audio Output) * * Copyright 2012 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,12 +48,8 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) //we should actually loop through the list of client formats here //and see if we can send the client something that it supports... -<<<<<<< HEAD - -======= WLog_DBG(TAG, "Client supports the following %d formats: ", context->num_client_formats); ->>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a for (i = 0; i < context->num_client_formats; i++) { /* TODO: improve the way we agree on a format */ @@ -61,10 +59,7 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) (context->client_formats[i].nChannels == context->server_formats[j].nChannels) && (context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec)) { -<<<<<<< HEAD -======= WLog_DBG(TAG, "agreed on format!"); ->>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a formatAgreed = TRUE; agreedFormat = (AUDIO_FORMAT*)&context->server_formats[j]; break; @@ -77,10 +72,7 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) if (formatAgreed == FALSE) { -<<<<<<< HEAD -======= WLog_DBG(TAG, "Could not agree on a audio format with the server"); ->>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a return; } @@ -123,11 +115,7 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) if (status != noErr) { -<<<<<<< HEAD - -======= WLog_DBG(TAG, "Failed to create a new Audio Queue. Status code: %d", status); ->>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a } UInt32 dataFormatSize = sizeof (recorderState.dataFormat); @@ -164,6 +152,7 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) BOOL mf_peer_rdpsnd_init(mfPeerContext* context) { context->rdpsnd = rdpsnd_server_context_new(context->vcm); + context->rdpsnd->rdpcontext = &context->_p; context->rdpsnd->data = context; context->rdpsnd->server_formats = supported_audio_formats; @@ -223,11 +212,7 @@ void mf_peer_rdpsnd_input_callback (void *inUserD if (status != noErr) { -<<<<<<< HEAD - -======= WLog_DBG(TAG, "AudioQueueEnqueueBuffer() returned status = %d", status); ->>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a } } diff --git a/server/Sample/sf_audin.c b/server/Sample/sf_audin.c index 1191aa4..f5069c7 100644 --- a/server/Sample/sf_audin.c +++ b/server/Sample/sf_audin.c @@ -62,6 +62,7 @@ static WIN32ERROR sf_peer_audin_receive_samples(audin_server_context* context, c void sf_peer_audin_init(testPeerContext* context) { context->audin = audin_server_context_new(context->vcm); + context->audin->rdpcontext = &context->_p; context->audin->data = context; context->audin->server_formats = test_audio_formats; diff --git a/server/Sample/sf_encomsp.c b/server/Sample/sf_encomsp.c index a152182..00a5a86 100644 --- a/server/Sample/sf_encomsp.c +++ b/server/Sample/sf_encomsp.c @@ -3,6 +3,8 @@ * FreeRDP Sample Server (Lync Multiparty) * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +28,7 @@ BOOL sf_peer_encomsp_init(testPeerContext* context) { context->encomsp = encomsp_server_context_new(context->vcm); + context->encomsp->rdpcontext = &context->_p; if (!context->encomsp) return FALSE; diff --git a/server/Sample/sf_rdpsnd.c b/server/Sample/sf_rdpsnd.c index 0475b9f..63fcb75 100644 --- a/server/Sample/sf_rdpsnd.c +++ b/server/Sample/sf_rdpsnd.c @@ -3,6 +3,8 @@ * FreeRDP Sample Server (Audio Output) * * Copyright 2012 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +45,7 @@ static void sf_peer_rdpsnd_activated(RdpsndServerContext* context) BOOL sf_peer_rdpsnd_init(testPeerContext* context) { context->rdpsnd = rdpsnd_server_context_new(context->vcm); + context->rdpsnd->rdpcontext = &context->_p; context->rdpsnd->data = context; context->rdpsnd->server_formats = test_audio_formats; @@ -56,7 +59,10 @@ BOOL sf_peer_rdpsnd_init(testPeerContext* context) context->rdpsnd->Activated = sf_peer_rdpsnd_activated; - context->rdpsnd->Initialize(context->rdpsnd, TRUE); + if (context->rdpsnd->Initialize(context->rdpsnd, TRUE) != CHANNEL_RC_OK) + { + return FALSE; + } return TRUE; } diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 3fdffe1..3465571 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -151,6 +151,7 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) return FALSE; context->rdpsnd = rdpsnd_server_context_new(context->vcm); + context->rdpsnd->rdpcontext = &context->_p; context->rdpsnd->data = context; context->rdpsnd->server_formats = supported_audio_formats; diff --git a/server/shadow/shadow_encomsp.c b/server/shadow/shadow_encomsp.c index 7e8cc2c..8fa9a37 100644 --- a/server/shadow/shadow_encomsp.c +++ b/server/shadow/shadow_encomsp.c @@ -2,6 +2,8 @@ * FreeRDP: A Remote Desktop Protocol Implementation * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -99,6 +101,8 @@ int shadow_client_encomsp_init(rdpShadowClient* client) encomsp = client->encomsp = encomsp_server_context_new(client->vcm); + encomsp->rdpcontext = &client->context; + encomsp->custom = (void*) client; encomsp->ChangeParticipantControlLevel = encomsp_change_participant_control_level; diff --git a/server/shadow/shadow_remdesk.c b/server/shadow/shadow_remdesk.c index 5e7b273..977f051 100644 --- a/server/shadow/shadow_remdesk.c +++ b/server/shadow/shadow_remdesk.c @@ -2,6 +2,8 @@ * FreeRDP: A Remote Desktop Protocol Implementation * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +31,7 @@ int shadow_client_remdesk_init(rdpShadowClient* client) RemdeskServerContext* remdesk; remdesk = client->remdesk = remdesk_server_context_new(client->vcm); + remdesk->rdpcontext = &client->context; remdesk->custom = (void*) client;