introduced channel error reporting system
authorMartin Haimberger <martin.haimberger@thincast.com>
Wed, 15 Jul 2015 07:50:35 +0000 (00:50 -0700)
committerMartin Haimberger <martin.haimberger@thincast.com>
Wed, 15 Jul 2015 07:50:35 +0000 (00:50 -0700)
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.

74 files changed:
channels/audin/client/alsa/audin_alsa.c
channels/audin/client/audin_main.c
channels/audin/client/opensles/audin_opensl_es.c
channels/audin/client/oss/audin_oss.c
channels/audin/client/pulse/audin_pulse.c
channels/audin/client/winmm/audin_winmm.c
channels/audin/server/audin.c
channels/cliprdr/client/cliprdr_main.c
channels/cliprdr/client/cliprdr_main.h
channels/cliprdr/server/cliprdr_main.c
channels/drdynvc/client/drdynvc_main.c
channels/drdynvc/client/drdynvc_main.h
channels/drdynvc/server/drdynvc_main.c
channels/drive/client/drive_main.c
channels/echo/server/echo_main.c
channels/encomsp/client/encomsp_main.c
channels/encomsp/client/encomsp_main.h
channels/encomsp/server/encomsp_main.c
channels/parallel/client/parallel_main.c
channels/printer/client/printer_main.c
channels/rail/client/rail_main.c
channels/rail/client/rail_main.h
channels/rdpdr/client/devman.c
channels/rdpdr/client/devman.h
channels/rdpdr/client/rdpdr_main.c
channels/rdpdr/client/rdpdr_main.h
channels/rdpdr/server/rdpdr_main.c
channels/rdpei/client/rdpei_main.c
channels/rdpgfx/client/rdpgfx_main.c
channels/rdpgfx/client/rdpgfx_main.h
channels/rdpsnd/client/alsa/rdpsnd_alsa.c
channels/rdpsnd/client/ios/rdpsnd_ios.c
channels/rdpsnd/client/mac/rdpsnd_mac.c
channels/rdpsnd/client/opensles/rdpsnd_opensles.c
channels/rdpsnd/client/oss/rdpsnd_oss.c
channels/rdpsnd/client/pulse/rdpsnd_pulse.c
channels/rdpsnd/client/rdpsnd_main.c
channels/rdpsnd/client/winmm/rdpsnd_winmm.c
channels/rdpsnd/server/rdpsnd_main.c
channels/remdesk/client/remdesk_main.c
channels/remdesk/client/remdesk_main.h
channels/remdesk/server/remdesk_main.c
channels/serial/client/serial_main.c
channels/smartcard/client/smartcard_main.c
channels/smartcard/client/smartcard_main.h
channels/tsmf/client/tsmf_ifman.c
channels/tsmf/client/tsmf_ifman.h
channels/tsmf/client/tsmf_main.c
channels/tsmf/client/tsmf_main.h
channels/tsmf/client/tsmf_media.c
channels/tsmf/client/tsmf_media.h
include/freerdp/channels/rdpdr.h
include/freerdp/client/audin.h
include/freerdp/client/cliprdr.h
include/freerdp/client/rdpsnd.h
include/freerdp/freerdp.h
include/freerdp/server/audin.h
include/freerdp/server/cliprdr.h
include/freerdp/server/echo.h
include/freerdp/server/encomsp.h
include/freerdp/server/rdpdr.h
include/freerdp/server/rdpsnd.h
include/freerdp/server/remdesk.h
include/freerdp/svc.h
libfreerdp/core/client.c
libfreerdp/core/freerdp.c
server/Mac/mf_audin.c
server/Mac/mf_rdpsnd.c
server/Sample/sf_audin.c
server/Sample/sf_encomsp.c
server/Sample/sf_rdpsnd.c
server/Windows/wf_rdpsnd.c
server/shadow/shadow_encomsp.c
server/shadow/shadow_remdesk.c

index 0f4b042..93a5a0d 100644 (file)
@@ -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;
 
index 1284986..6aaa8c2 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <winpr/stream.h>
 #include <winpr/win32error.h>
+#include <freerdp/freerdp.h>
 #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);
index 841b1e4..4db37ce 100644 (file)
@@ -39,6 +39,7 @@
 #include <freerdp/channels/rdpsnd.h>
 
 #include <SLES/OpenSLES.h>
+#include <freerdp/client/audin.h>
 
 #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;
 
index b45f7b7..b8b54b1 100644 (file)
@@ -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;
 
index a5cd78a..c617b09 100644 (file)
@@ -36,6 +36,7 @@
 #include <freerdp/types.h>
 #include <freerdp/addin.h>
 #include <freerdp/codec/dsp.h>
+#include <freerdp/client/audin.h>
 
 #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;
 
index c651feb..3e5f13b 100644 (file)
@@ -33,6 +33,7 @@
 #include <winpr/crt.h>
 #include <winpr/cmdline.h>
 #include <freerdp/addin.h>
+#include <freerdp/client/audin.h>
 
 #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;
 
index 982f99a..d64ee75 100644 (file)
@@ -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)))
                {
index 42f1be8..6deb301 100644 (file)
@@ -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");
index da78822..aea9589 100644 (file)
@@ -50,7 +50,6 @@ struct cliprdr_plugin
        BOOL streamFileClipEnabled;
        BOOL fileClipNoFilePaths;
        BOOL canLockClipData;
-       WIN32ERROR error;
 };
 typedef struct cliprdr_plugin cliprdrPlugin;
 
index 85b01a3..a2f7c42 100644 (file)
@@ -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)))
        {
index 213b4fa..cb55240 100644 (file)
@@ -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;
        }
index 0562434..cdd19f9 100644 (file)
@@ -34,6 +34,7 @@
 #include <freerdp/addin.h>
 #include <freerdp/channels/log.h>
 #include <freerdp/client/drdynvc.h>
+#include <freerdp/freerdp.h>
 
 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;
 };
index f07d2b2..1baebdc 100644 (file)
@@ -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)))
        {
index 643192b..b71a2f1 100644 (file)
@@ -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);
index b0cff2b..ff881bc 100644 (file)
@@ -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;
 }
index 24ea995..a4884a1 100644 (file)
@@ -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;
        }
 
index 5aea1b2..e226d96 100644 (file)
@@ -49,7 +49,7 @@ struct encomsp_plugin
        void* InitHandle;
        DWORD OpenHandle;
        wMessageQueue* queue;
-       WIN32ERROR error;
+       rdpContext* rdpcontext;
 };
 typedef struct encomsp_plugin encomspPlugin;
 
index 6547815..02ac629 100644 (file)
@@ -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;
 }
index 0d264fc..3991ddf 100644 (file)
@@ -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);
index 644e471..b479c60 100644 (file)
@@ -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;
 
index 6af3b5f..10168c0 100644 (file)
@@ -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;
index 62d1d55..91a15ae 100644 (file)
@@ -49,7 +49,7 @@ struct rail_plugin
        void* InitHandle;
        DWORD OpenHandle;
        wMessageQueue* queue;
-       WIN32ERROR error;
+       rdpContext* rdpcontext;
 };
 typedef struct rail_plugin railPlugin;
 
index 7086521..02069c4 100644 (file)
@@ -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);
 }
index 0db2c13..d5589b5 100644 (file)
@@ -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);
index 939cc95..54aa5da 100644 (file)
@@ -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));
 
 
index 39fbc58..8ba82fa 100644 (file)
@@ -67,7 +67,7 @@ struct rdpdr_plugin
 #else
        HANDLE stopEvent;
 #endif
-       WIN32ERROR error;
+       rdpContext* rdpcontext;
 };
 
 WIN32ERROR rdpdr_send(rdpdrPlugin* rdpdr, wStream* s);
index 5df576c..b2ec4cf 100644 (file)
@@ -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;
 }
 
index adf549a..15db248 100644 (file)
@@ -36,6 +36,7 @@
 #include <winpr/collections.h>
 
 #include <freerdp/addin.h>
+#include <freerdp/freerdp.h>
 
 #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!");
index 2db0ee3..580f256 100644 (file)
@@ -1381,6 +1381,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
 
                gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
 
+
                context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext));
 
                if (!context)
index 96d91b4..380292d 100644 (file)
@@ -30,6 +30,7 @@
 #include <freerdp/client/rdpgfx.h>
 #include <freerdp/channels/log.h>
 #include <freerdp/codec/zgfx.h>
+#include <freerdp/freerdp.h>
 
 #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;
 
index 1f395be..7a6d324 100644 (file)
@@ -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 <martin.haimberger@thincast.com>
  *
  * 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;
 }
index f0ede99..2266864 100644 (file)
@@ -3,6 +3,8 @@
  * Audio Output Virtual Channel
  *
  * Copyright 2013 Dell Software <Mike.McDonald@software.dell.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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 <freerdp/types.h>
 #include <freerdp/codec/dsp.h>
+#include <winpr/win32error.h>
 
 #import <AudioToolbox/AudioToolbox.h>
 
@@ -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;
 }
index 1c9394d..5677235 100644 (file)
@@ -3,6 +3,8 @@
  * Audio Output Virtual Channel
  *
  * Copyright 2012 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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 <freerdp/types.h>
 #include <freerdp/codec/dsp.h>
+#include <winpr/win32error.h>
 
 #include <AudioToolbox/AudioToolbox.h>
 #include <AudioToolbox/AudioQueue.h>
@@ -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;
 }
index 9d920ec..4fd790b 100644 (file)
@@ -3,6 +3,8 @@
  * Audio Output Virtual Channel
  *
  * Copyright 2013 Armin Novak <armin.novak@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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 <winpr/cmdline.h>
 #include <winpr/sysinfo.h>
 #include <winpr/collections.h>
+#include <winpr/win32error.h>
 
 #include <freerdp/types.h>
 #include <freerdp/codec/dsp.h>
@@ -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;
 }
index 81aa4c8..df99c46 100644 (file)
@@ -3,6 +3,8 @@
  * Audio Output Virtual Channel
  *
  * Copyright (c) 2015 Rozhuk Ivan <rozhuk.im@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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;
 }
index c53991d..092a768 100644 (file)
@@ -3,6 +3,8 @@
  * Audio Output Virtual Channel
  *
  * Copyright 2011 Vic Lee
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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 <freerdp/types.h>
 #include <freerdp/codec/dsp.h>
+#include <winpr/win32error.h>
 
 #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;
index 246a0ac..0c40ad0 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright 2009-2011 Jay Sorg
  * Copyright 2010-2011 Vic Lee
  * Copyright 2012-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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");
index 0d87185..70e232d 100644 (file)
@@ -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 <martin.haimberger@thincast.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include <winpr/crt.h>
 #include <winpr/cmdline.h>
+#include <winpr/win32error.h>
 
 #include <freerdp/types.h>
 #include <freerdp/codec/dsp.h>
 #include <freerdp/channels/log.h>
+#include <winpr/win32error.h>
 
 #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;
 }
index 50d9d7f..eb9ca01 100644 (file)
@@ -3,6 +3,8 @@
  * Server Audio Virtual Channel
  *
  * Copyright 2012 Vic Lee
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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;
 }
index c23f212..4f37077 100644 (file)
@@ -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));
index 743da6c..59e92ca 100644 (file)
@@ -56,7 +56,7 @@ struct remdesk_plugin
        char* ExpertBlob;
        BYTE* EncryptedPassStub;
        int EncryptedPassStubSize;
-       WIN32ERROR error;
+       rdpContext* rdpcontext;
 };
 typedef struct remdesk_plugin remdeskPlugin;
 
index 9c18c86..1b3b490 100644 (file)
@@ -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)))
        {
index 620e10f..52c0081 100644 (file)
@@ -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);
index 9043184..b0b5654 100644 (file)
@@ -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);
index 09017df..96d925c 100644 (file)
@@ -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);
index 93bd1a7..ee6c55b 100644 (file)
@@ -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 <martin.haimberger@thincast.com>
  *
  * 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;
 
index c5e2cb8..056d4db 100644 (file)
@@ -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 <martin.haimberger@thincast.com>
  *
  * 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 <freerdp/freerdp.h>
+
 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);
index 930f1a1..648774a 100644 (file)
@@ -3,6 +3,8 @@
  * Video Redirection Virtual Channel
  *
  * Copyright 2010-2011 Vic Lee
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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));
        }
index 04f8f4c..e29a00a 100644 (file)
@@ -3,6 +3,8 @@
  * Video Redirection Virtual Channel
  *
  * Copyright 2010-2011 Vic Lee
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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 <freerdp/freerdp.h>
+
 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,
index 6ab2d73..f6e045f 100644 (file)
@@ -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 <martin.haimberger@thincast.com>
  *
  * 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:
index f26f16a..4ed51f8 100644 (file)
@@ -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 <martin.haimberger@thincast.com>
  *
  * 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 <freerdp/freerdp.h>
+
 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);
index 7ada8cb..cc3c412 100644 (file)
@@ -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 */
index eff3196..6e2125c 100644 (file)
@@ -23,6 +23,7 @@
 #define FREERDP_CHANNEL_CLIENT_AUDIN_H
 
 #include <freerdp/channels/audin.h>
+#include <freerdp/freerdp.h>
 
 /**
  * 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;
index 8fb2c95..f5576a0 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <freerdp/message.h>
 #include <freerdp/channels/cliprdr.h>
+#include <freerdp/freerdp.h>
 
 /**
  * Client Interface
@@ -80,6 +81,8 @@ struct _cliprdr_client_context
        pcCliprdrServerFileContentsRequest ServerFileContentsRequest;
        pcCliprdrClientFileContentsResponse ClientFileContentsResponse;
        pcCliprdrServerFileContentsResponse ServerFileContentsResponse;
+
+       rdpContext* rdpcontext;
 };
 
 struct _CLIPRDR_FORMAT_NAME
index 7e482ae..544b231 100644 (file)
@@ -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 */
 
index 2df5e4c..6bb0ff4 100644 (file)
@@ -3,8 +3,8 @@
  * FreeRDP Interface
  *
  * Copyright 2009-2011 Jay Sorg
- * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
- *
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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
index f935ac1..d441411 100644 (file)
@@ -91,6 +91,8 @@ struct _audin_server_context
         * server must be careful of thread synchronization.
         */
        psAudinServerReceiveSamples ReceiveSamples;
+
+       rdpContext* rdpcontext;
 };
 
 #ifdef __cplusplus
index 5fbeb17..1477dc6 100644 (file)
@@ -95,6 +95,8 @@ struct _cliprdr_server_context
        psCliprdrServerFileContentsRequest ServerFileContentsRequest;
        psCliprdrClientFileContentsResponse ClientFileContentsResponse;
        psCliprdrServerFileContentsResponse ServerFileContentsResponse;
+
+       rdpContext* rdpcontext;
 };
 
 #ifdef __cplusplus
index ecd64c2..fbf21dc 100644 (file)
@@ -72,6 +72,8 @@ struct _echo_server_context
         * Receive echo response PDU.
         */
        psEchoServerResponse Response;
+
+       rdpContext* rdpcontext;
 };
 
 #ifdef __cplusplus
index 678b360..dbc9e84 100644 (file)
@@ -71,6 +71,8 @@ struct _encomsp_server_context
        psEncomspGraphicsStreamResumed GraphicsStreamResumed;
 
        EncomspServerPrivate* priv;
+
+       rdpContext* rdpcontext;
 };
 
 #ifdef __cplusplus
index df65090..b980213 100644 (file)
@@ -137,6 +137,8 @@ struct _rdpdr_server_context
        /*** Smartcard callbacks registered by the server. ***/
        psRdpdrOnSmartcardCreate OnSmartcardCreate;
        psRdpdrOnSmartcardDelete OnSmartcardDelete;
+
+       rdpContext* rdpcontext;
 };
 
 #ifdef __cplusplus
index 6aff908..a2e2fe8 100644 (file)
@@ -3,6 +3,8 @@
  * Server Audio Virtual Channel
  *
  * Copyright 2012 Vic Lee
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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
index 6d61b2e..d442949 100644 (file)
@@ -47,6 +47,7 @@ struct _remdesk_server_context
        psRemdeskStop Stop;
 
        RemdeskServerPrivate* priv;
+       rdpContext* rdpcontext;
 };
 
 #ifdef __cplusplus
index d424770..c6843cc 100644 (file)
@@ -3,6 +3,8 @@
  * Static Virtual Channel Interface
  *
  * Copyright 2009-2011 Jay Sorg
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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 <freerdp/types.h>
 
 #include <winpr/wtsapi.h>
+#include <freerdp/freerdp.h>
 
 #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;
index 2001feb..5bbe1df 100644 (file)
@@ -3,6 +3,8 @@
  * Client Channels
  *
  * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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;
index a220b9b..e1fa5cb 100644 (file)
@@ -3,7 +3,8 @@
  * FreeRDP Core
  *
  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
- * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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);
+}
index be96d2f..368a4b4 100644 (file)
@@ -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;
index 1580a43..b8c18a4 100644 (file)
@@ -3,6 +3,8 @@
  * FreeRDP Mac OS X Server (Audio Output)
  *
  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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
        }
        
 }
index 1191aa4..f5069c7 100644 (file)
@@ -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;
index a152182..00a5a86 100644 (file)
@@ -3,6 +3,8 @@
  * FreeRDP Sample Server (Lync Multiparty)
  *
  * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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;
index 0475b9f..63fcb75 100644 (file)
@@ -3,6 +3,8 @@
  * FreeRDP Sample Server (Audio Output)
  *
  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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;
 }
index 3fdffe1..3465571 100644 (file)
@@ -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;
index 7e8cc2c..8fa9a37 100644 (file)
@@ -2,6 +2,8 @@
  * FreeRDP: A Remote Desktop Protocol Implementation
  *
  * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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;
index 5e7b273..977f051 100644 (file)
@@ -2,6 +2,8 @@
  * FreeRDP: A Remote Desktop Protocol Implementation
  *
  * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  *
  * 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;