AudinReceive receive;
void* user_data;
+
+ rdpContext* rdpcontext;
} AudinALSADevice;
static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_handle)
{
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;
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;
}
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;
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)))
{
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;
#include <winpr/stream.h>
#include <winpr/win32error.h>
+#include <freerdp/freerdp.h>
#include "audin_main.h"
#define MSG_SNDIN_VERSION 0x01
/* Device interface */
IAudinDevice* device;
+
+ rdpContext* rdpcontext;
};
static WIN32ERROR audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
entryPoints.plugin = pPlugin;
entryPoints.pRegisterAudinDevice = audin_register_device_plugin;
entryPoints.args = args;
+ entryPoints.rdpcontext = ((AUDIN_PLUGIN*)pPlugin)->rdpcontext;
if ((error = entry(&entryPoints)))
{
}
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);
#include <freerdp/channels/rdpsnd.h>
#include <SLES/OpenSLES.h>
+#include <freerdp/client/audin.h>
#include "audin_main.h"
#include "opensl_io.h"
HANDLE stopEvent;
void* user_data;
+
+ rdpContext* rdpcontext;
} AudinOpenSLESDevice;
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);
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;
}
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;
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;
}
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;
}
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)))
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;
AudinReceive receive;
void* user_data;
+
+ rdpContext* rdpcontext;
} AudinOSSDevice;
#define OSS_LOG_ERR(_text, _error) \
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. */
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;
}
/* 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;
}
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);
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)))
{
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;
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/codec/dsp.h>
+#include <freerdp/client/audin.h>
#include "audin_main.h"
AudinReceive receive;
void* user_data;
+
+ rdpContext* rdpcontext;
} AudinPulseDevice;
static void audin_pulse_context_state_callback(pa_context* context, void* userdata)
{
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
{
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;
}
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;
}
pa_stream_drop(stream);
+
+ if (error && pulse->rdpcontext)
+ setChannelError(pulse->rdpcontext, error, "audin_oss_thread_func reported an error");
}
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");
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;
#include <winpr/crt.h>
#include <winpr/cmdline.h>
#include <freerdp/addin.h>
+#include <freerdp/client/audin.h>
#include "audin_main.h"
UINT32 ppwfx_size;
UINT32 cFormats;
UINT32 frames_per_packet;
+ rdpContext* rdpcontext;
} AudinWinmmDevice;
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)
{
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;
default:
break;
}
+ if (error && winmm->rdpcontext)
+ setChannelError(winmm->rdpcontext, error, "waveInProc reported an error");
}
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;
}
}
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);
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);
}
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)))
{
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;
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;
}
return FALSE;
}
- // TODO: implement signaling an error
if (!(audin->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL)))
{
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;
}
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:
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)
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;
}
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;
}
*(pEntryPointsEx->ppInterface) = (void*) context;
cliprdr->context = context;
+ context->rdpcontext = pEntryPointsEx->context;
}
cliprdr->log = WLog_Get("com.freerdp.channels.cliprdr.client");
BOOL streamFileClipEnabled;
BOOL fileClipNoFilePaths;
BOOL canLockClipData;
- WIN32ERROR error;
};
typedef struct cliprdr_plugin cliprdrPlugin;
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)
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(cliprdr->StopEvent, 0) == WAIT_OBJECT_0)
- {
break;
- }
if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
{
}
}
}
+out:
+ if (error && context->rdpcontext)
+ setChannelError(context->rdpcontext, error, "cliprdr_server_thread reported an error");
+
ExitThread((DWORD)error);
return NULL;
}
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)))
{
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;
}
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;
}
if (status != CHANNEL_RC_OK)
{
- drdynvc->channel_error = status;
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
return status;
status = drdynvc_send_capability_response(drdynvc);
- drdynvc->channel_error = status;
-
drdynvc->state = DRDYNVC_STATE_READY;
return status;
error = drdynvc_send(drdynvc, data_out);
- drdynvc->channel_error = error;
-
if (error)
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(error), error);
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;
}
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:
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)
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;
}
return error;
}
-
drdynvc->queue = MessageQueue_New(NULL);
if (!drdynvc->queue)
{
WLog_ERR(TAG, "dvcman_new failed!");
goto error;
}
- drdynvc->channel_error = CHANNEL_RC_OK;
settings = (rdpSettings*) drdynvc->channelEntryPoints.pExtendedData;
goto error;
}
+ return CHANNEL_RC_OK;
+
error:
drdynvc_remove_open_handle_data(drdynvc->OpenHandle);
MessageQueue_Free(drdynvc->queue);
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");
+
}
/**
drdynvc->context = context;
context->GetVersion = drdynvc_get_version;
+ drdynvc->rdpcontext = pEntryPointsEx->context;
*(pEntryPointsEx->ppInterface) = (void*) context;
}
#include <freerdp/addin.h>
#include <freerdp/channels/log.h>
#include <freerdp/client/drdynvc.h>
+#include <freerdp/freerdp.h>
typedef struct drdynvc_plugin drdynvcPlugin;
int PriorityCharge1;
int PriorityCharge2;
int PriorityCharge3;
- WIN32ERROR channel_error;
+ rdpContext* rdpcontext;
+
IWTSVirtualChannelManager* channel_mgr;
};
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;
}
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)))
{
wMessageQueue* IrpQueue;
DEVMAN* devman;
+
+ rdpContext* rdpcontext;
};
static UINT32 drive_map_posix_err(int fs_errno)
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;
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;
}
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);
{
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;
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;
}
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;
}
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:
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)
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;
}
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:
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 */
EncomspClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
BOOL isFreerdp = FALSE;
+ WIN32ERROR error;
encomsp = (encomspPlugin*) calloc(1, sizeof(encomspPlugin));
if (!encomsp)
*(pEntryPointsEx->ppInterface) = (void*) context;
encomsp->context = context;
+ encomsp->rdpcontext = pEntryPointsEx->context;
isFreerdp = TRUE;
}
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;
}
void* InitHandle;
DWORD OpenHandle;
wMessageQueue* queue;
- WIN32ERROR error;
+ rdpContext* rdpcontext;
};
typedef struct encomsp_plugin encomspPlugin;
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)
}
Stream_Free(s, TRUE);
+out:
+ if (error && context->rdpcontext)
+ setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error");
+
ExitThread((DWORD)error);
return NULL;
}
HANDLE thread;
wMessageQueue* queue;
+ rdpContext* rdpcontext;
};
typedef struct _PARALLEL_DEVICE PARALLEL_DEVICE;
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;
break;
}
}
+ if (error && parallel->rdpcontext)
+ setChannelError(parallel->rdpcontext, error, "parallel_thread_func reported an error");
+
ExitThread((DWORD)error);
return NULL;
}
{
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;
}
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);
HANDLE stopEvent;
HANDLE thread;
+ rdpContext* rdpcontext;
};
static WIN32ERROR printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp)
break;
}
}
+ if (error && printer_dev->rdpcontext)
+ setChannelError(printer_dev->rdpcontext, error, "printer_thread_func reported an error");
ExitThread((DWORD) error);
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;
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;
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;
}
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:
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)
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;
}
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;
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 */
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;
void* InitHandle;
DWORD OpenHandle;
wMessageQueue* queue;
- WIN32ERROR error;
+ rdpContext* rdpcontext;
};
typedef struct rail_plugin railPlugin;
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;
ep.devman = devman;
ep.RegisterDevice = devman_register_device;
ep.device = device;
+ ep.rdpcontext = rdpcontext;
- entry(&ep);
-
- return CHANNEL_RC_OK;
+ return entry(&ep);
}
#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);
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;
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);
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;
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:
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;
}
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:
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)
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;
}
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;
}
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:
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 */
{
UINT rc;
rdpdrPlugin* rdpdr;
+ CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
+
rdpdr = (rdpdrPlugin*) calloc(1, sizeof(rdpdrPlugin));
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));
#else
HANDLE stopEvent;
#endif
- WIN32ERROR error;
+ rdpContext* rdpcontext;
};
WIN32ERROR rdpdr_send(rdpdrPlugin* rdpdr, wStream* s);
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)
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)
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;
}
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;
}
#include <winpr/collections.h>
#include <freerdp/addin.h>
+#include <freerdp/freerdp.h>
#include "rdpei_common.h"
HANDLE thread;
CRITICAL_SECTION lock;
+ rdpContext* rdpcontext;
};
typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN;
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)
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)
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;
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!");
gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
+
context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext));
if (!context)
#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")
UINT16 MaxCacheSlot;
void* CacheSlots[25600];
+ rdpContext* rdpcontext;
};
typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN;
*
* 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.
{ 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;
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;
}
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;
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;
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);
free(alsa->device_name);
error_parse_args:
free(alsa);
- return -1;
+ return error;
}
* 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.
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
+#include <winpr/win32error.h>
#import <AudioToolbox/AudioToolbox.h>
#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;
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p);
- return 0;
+ return CHANNEL_RC_OK;
}
* 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.
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
+#include <winpr/win32error.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioToolbox/AudioQueue.h>
UInt32 DecodeBufferSizeFrames;
UInt32 propertySize = sizeof(DecodeBufferSizeFrames);
- AudioQueueGetProperty(mac->audioQueue,
+ status = AudioQueueGetProperty(mac->audioQueue,
kAudioQueueProperty_DecodeBufferSizeFrames,
&DecodeBufferSizeFrames,
&propertySize);
#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;
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac);
- return 0;
+ return CHANNEL_RC_OK;
}
* 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.
#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>
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;
{
opensles->device_name = _strdup("default");
if (!opensles->device_name)
- return ERROR_OUTOFMEMORY;
+ {
+ error = CHANNEL_RC_NO_MEMORY;
+ goto outstrdup;
+ }
}
opensles->rate = 44100;
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;
}
* 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.
#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;
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;
}
* 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.
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
+#include <winpr/win32error.h>
#include "rdpsnd_main.h"
#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;
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;
goto error;
}
- ret = ERROR_OUTOFMEMORY;
+ ret = CHANNEL_RC_NO_MEMORY;
pulse->dsp_context = freerdp_dsp_context_new();
if (!pulse->dsp_context)
goto error;
* 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.
/* Device plugin */
rdpsndDevicePlugin* device;
+ rdpContext* rdpcontext;
};
static WIN32ERROR rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave);
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;
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;
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;
}
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 */
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 */
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 */
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);
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;
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;
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)
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
{
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
{
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
{
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
{
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
{
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
{
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
{
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
{
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;
WIN32ERROR rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
{
- WIN32ERROR status = CHANNEL_RC_OK;
+ WIN32ERROR status;
if (!rdpsnd)
{
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)
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)
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);
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:
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)
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;
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);
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)
}
rdpsnd_remove_open_handle_data(rdpsnd->OpenHandle);
+
+ return CHANNEL_RC_OK;
}
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);
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 */
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)
{
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");
*
* 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"
#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;
winmm = (rdpsndWinmmPlugin*) calloc(1, sizeof(rdpsndWinmmPlugin));
if (!winmm)
- return -1;
+ return CHANNEL_RC_NO_MEMORY;
winmm->device.DisableConfirmThread = TRUE;
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;
}
* 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.
#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;
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 */
/* 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);
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)
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)
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;
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;
if (format->nSamplesPerSec == 0)
{
WLog_ERR(TAG, "invalid Client Sound Format!!");
- return FALSE;
+ return ERROR_INVALID_DATA;
}
switch(format->wFormatTag)
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;
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;
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 */
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)
{
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;
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;
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)))
{
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);
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)
{
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)
context = (RdpsndServerContext *)calloc(1, sizeof(RdpsndServerContext));
if (!context)
+ {
+ WLog_ERR(TAG, "calloc failed!");
return NULL;
+ }
context->vcm = 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;
*
* @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;
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);
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;
}
}
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;
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;
}
static WIN32ERROR remdesk_process_receive(remdeskPlugin* remdesk, wStream* s)
{
- WIN32ERROR status = CHANNEL_RC_OK;
+ WIN32ERROR status;
REMDESK_CHANNEL_HEADER header;
#if 0
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;
}
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:
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)
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;
}
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 */
*(pEntryPointsEx->ppInterface) = (void*) context;
remdesk->context = context;
+ remdesk->rdpcontext = pEntryPointsEx->context;
}
CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
char* ExpertBlob;
BYTE* EncryptedPassStub;
int EncryptedPassStubSize;
- WIN32ERROR error;
+ rdpContext* rdpcontext;
};
typedef struct remdesk_plugin remdeskPlugin;
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)
else
{
WLog_ERR(TAG, "WTSVirtualChannelQuery failed!");
- ExitThread(ERROR_INTERNAL_ERROR);
- return NULL;
+ error = ERROR_INTERNAL_ERROR;
+ goto out;
}
nCount = 0;
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)
}
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;
}
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)))
{
wListDictionary *IrpThreads;
UINT32 IrpThreadToBeTerminatedCount;
CRITICAL_SECTION TerminatingIrpThreadsLock;
+ rdpContext* rdpcontext;
};
typedef struct _IRP_THREAD_DATA IRP_THREAD_DATA;
/* 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;
}
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;
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;
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)
{
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;
}
* 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;
}
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);
wMessage message;
SMARTCARD_DEVICE* smartcard;
SMARTCARD_OPERATION* operation;
+ WIN32ERROR error = CHANNEL_RC_OK;
smartcard = pContext->smartcard;
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;
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;
}
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:
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
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)
{
}
}
out:
- //TODO signal error
+ if (error && smartcard->rdpcontext)
+ setChannelError(smartcard->rdpcontext, error, "smartcard_thread_func reported an error");
+
ExitThread((DWORD)error);
return NULL;
}
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;
}
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);
wQueue* CompletedIrpQueue;
wListDictionary* rgSCardContextList;
wListDictionary* rgOutstandingMessages;
+ rdpContext* rdpcontext;
};
SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTEXT hContext);
*
* 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.
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;
{
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;
* 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.
#ifndef __TSMF_IFMAN_H
#define __TSMF_IFMAN_H
+#include <freerdp/freerdp.h>
+
typedef struct _TSMF_IFMAN TSMF_IFMAN;
struct _TSMF_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);
* 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.
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:
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");
{
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;
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));
}
* 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.
#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;
const char* decoder_name;
const char* audio_name;
const char* audio_device;
+
+ rdpContext* rdpcontext;
};
BOOL tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
*
* 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.
wQueue *sample_list;
wQueue *sample_ack_list;
+ rdpContext* rdpcontext;
};
struct _TSMF_SAMPLE
{
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;
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;
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);
if (sample && !tsmf_sample_playback(sample))
{
WLog_ERR(TAG, "error playing sample");
+ error = ERROR_INTERNAL_ERROR;
break;
}
}
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;
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);
if (ArrayList_Add(presentation->stream_list, stream) < 0)
goto error_add;
+ stream->rdpcontext = rdpcontext;
+
return stream;
error_add:
*
* 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.
#ifndef __TSMF_MEDIA_H
#define __TSMF_MEDIA_H
+#include <freerdp/freerdp.h>
+
typedef struct _TSMF_PRESENTATION TSMF_PRESENTATION;
typedef struct _TSMF_STREAM TSMF_STREAM;
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);
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 */
#define FREERDP_CHANNEL_CLIENT_AUDIN_H
#include <freerdp/channels/audin.h>
+#include <freerdp/freerdp.h>
/**
* Subsystem Interface
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;
#include <freerdp/message.h>
#include <freerdp/channels/cliprdr.h>
+#include <freerdp/freerdp.h>
/**
* Client Interface
pcCliprdrServerFileContentsRequest ServerFileContentsRequest;
pcCliprdrClientFileContentsResponse ClientFileContentsResponse;
pcCliprdrServerFileContentsResponse ServerFileContentsResponse;
+
+ rdpContext* rdpcontext;
};
struct _CLIPRDR_FORMAT_NAME
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 */
* 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.
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.
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
* server must be careful of thread synchronization.
*/
psAudinServerReceiveSamples ReceiveSamples;
+
+ rdpContext* rdpcontext;
};
#ifdef __cplusplus
psCliprdrServerFileContentsRequest ServerFileContentsRequest;
psCliprdrClientFileContentsResponse ClientFileContentsResponse;
psCliprdrServerFileContentsResponse ServerFileContentsResponse;
+
+ rdpContext* rdpcontext;
};
#ifdef __cplusplus
* Receive echo response PDU.
*/
psEchoServerResponse Response;
+
+ rdpContext* rdpcontext;
};
#ifdef __cplusplus
psEncomspGraphicsStreamResumed GraphicsStreamResumed;
EncomspServerPrivate* priv;
+
+ rdpContext* rdpcontext;
};
#ifdef __cplusplus
/*** Smartcard callbacks registered by the server. ***/
psRdpdrOnSmartcardCreate OnSmartcardCreate;
psRdpdrOnSmartcardDelete OnSmartcardDelete;
+
+ rdpContext* rdpcontext;
};
#ifdef __cplusplus
* 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.
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);
* MS-RDPEA channel version the client announces
*/
UINT16 clientVersion;
+
+ rdpContext* rdpcontext;
};
#ifdef __cplusplus
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
psRemdeskStop Stop;
RemdeskServerPrivate* priv;
+ rdpContext* rdpcontext;
};
#ifdef __cplusplus
* 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.
#include <freerdp/types.h>
#include <winpr/wtsapi.h>
+#include <freerdp/freerdp.h>
#define CHANNEL_EVENT_USER 1000
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;
* 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.
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;
* 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.
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;
status = freerdp_channels_check_fds(context->channels, context->instance);
+ if (!status)
+ return FALSE;
+
+ status = checkChannelErrorEvent(context);
+
return status;
}
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:
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)
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);
+}
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;
* 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.
//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 */
(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;
if (formatAgreed == FALSE)
{
-<<<<<<< HEAD
-=======
WLog_DBG(TAG, "Could not agree on a audio format with the server");
->>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
return;
}
if (status != noErr)
{
-<<<<<<< HEAD
-
-=======
WLog_DBG(TAG, "Failed to create a new Audio Queue. Status code: %d", status);
->>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
}
UInt32 dataFormatSize = sizeof (recorderState.dataFormat);
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;
if (status != noErr)
{
-<<<<<<< HEAD
-
-=======
WLog_DBG(TAG, "AudioQueueEnqueueBuffer() returned status = %d", status);
->>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
}
}
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;
* 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.
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;
* 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.
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;
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;
}
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;
* 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.
encomsp = client->encomsp = encomsp_server_context_new(client->vcm);
+ encomsp->rdpcontext = &client->context;
+
encomsp->custom = (void*) client;
encomsp->ChangeParticipantControlLevel = encomsp_change_participant_control_level;
* 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.
RemdeskServerContext* remdesk;
remdesk = client->remdesk = remdesk_server_context_new(client->vcm);
+ remdesk->rdpcontext = &client->context;
remdesk->custom = (void*) client;