introduced channel error reporting system

The rdpContext gets an event which will
get set if an error occoured in a channel.

If a thread or a void callback has to report an
error it will get signaled by this system.
This commit is contained in:
Martin Haimberger 2015-07-15 00:50:35 -07:00
parent d9e2834a70
commit b8c110d19b
74 changed files with 1173 additions and 521 deletions

View File

@ -65,6 +65,8 @@ typedef struct _AudinALSADevice
AudinReceive receive;
void* user_data;
rdpContext* rdpcontext;
} AudinALSADevice;
static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_handle)
@ -148,9 +150,13 @@ static WIN32ERROR audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, in
{
if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM)
{
alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context,
if (!alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context,
alsa->buffer, alsa->buffer_frames * tbytes_per_frame,
alsa->target_channels, alsa->block_size);
alsa->target_channels, alsa->block_size))
{
ret = ERROR_INTERNAL_ERROR;
break;
}
encoded_data = alsa->dsp_context->adpcm_buffer;
encoded_size = alsa->dsp_context->adpcm_size;
@ -204,7 +210,8 @@ static void* audin_alsa_thread_func(void* arg)
if (!buffer)
{
WLog_ERR(TAG, "calloc failed!");
//TODO: signal error to freerdp
if (alsa->rdpcontext)
setChannelError(alsa->rdpcontext, CHANNEL_RC_NO_MEMORY, "calloc failed!");
ExitThread((DWORD)CHANNEL_RC_NO_MEMORY);
return NULL;
}
@ -255,6 +262,8 @@ static void* audin_alsa_thread_func(void* arg)
snd_pcm_close(capture_handle);
DEBUG_DVC("out");
if (error && alsa->rdpcontext)
setChannelError(alsa->rdpcontext, error, "audin_alsa_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
@ -363,7 +372,6 @@ static WIN32ERROR audin_alsa_open(IAudinDevice* device, AudinReceive receive, vo
WLog_ERR(TAG, "CreateEvent failed!");
goto error_out;
}
// TODO: add mechanism that threads can signal failure
if (!(alsa->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL)))
{
@ -469,6 +477,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POIN
alsa->iface.SetFormat = audin_alsa_set_format;
alsa->iface.Close = audin_alsa_close;
alsa->iface.Free = audin_alsa_free;
alsa->rdpcontext = pEntryPoints->rdpcontext;
args = pEntryPoints->args;

View File

@ -35,6 +35,7 @@
#include <winpr/stream.h>
#include <winpr/win32error.h>
#include <freerdp/freerdp.h>
#include "audin_main.h"
#define MSG_SNDIN_VERSION 0x01
@ -88,6 +89,8 @@ struct _AUDIN_PLUGIN
/* Device interface */
IAudinDevice* device;
rdpContext* rdpcontext;
};
static WIN32ERROR audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
@ -577,6 +580,7 @@ static WIN32ERROR audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name
entryPoints.plugin = pPlugin;
entryPoints.pRegisterAudinDevice = audin_register_device_plugin;
entryPoints.args = args;
entryPoints.rdpcontext = ((AUDIN_PLUGIN*)pPlugin)->rdpcontext;
if ((error = entry(&entryPoints)))
{
@ -715,6 +719,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
}
args = pEntryPoints->GetPluginData(pEntryPoints);
audin->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context;
if (error == CHANNEL_RC_OK)
audin_process_addin_args((IWTSPlugin*) audin, args);

View File

@ -39,6 +39,7 @@
#include <freerdp/channels/rdpsnd.h>
#include <SLES/OpenSLES.h>
#include <freerdp/client/audin.h>
#include "audin_main.h"
#include "opensl_io.h"
@ -66,6 +67,8 @@ typedef struct _AudinOpenSLESDevice
HANDLE stopEvent;
void* user_data;
rdpContext* rdpcontext;
} AudinOpenSLESDevice;
static void* audin_opensles_thread_func(void* arg)
@ -79,6 +82,7 @@ static void* audin_opensles_thread_func(void* arg)
AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) arg;
const size_t raw_size = opensles->frames_per_packet * opensles->bytes_per_channel;
int rc = CHANNEL_RC_OK;
WIN32ERROR error = CHANNEL_RC_OK;
DEBUG_DVC("opensles=%p", opensles);
@ -92,7 +96,8 @@ static void* audin_opensles_thread_func(void* arg)
if (!buffer.v)
{
WLog_ERR(TAG, "calloc failed!");
//TODO: signal error to freerdp
if (opensles->rdpcontext)
setChannelError(opensles->rdpcontext, CHANNEL_RC_NO_MEMORY, "audin_opensles_thread_func reported an error");
ExitThread((DWORD)CHANNEL_RC_NO_MEMORY);
return NULL;
}
@ -114,17 +119,25 @@ static void* audin_opensles_thread_func(void* arg)
assert(rc == raw_size);
if (opensles->format == WAVE_FORMAT_ADPCM)
{
opensles->dsp_context->encode_ms_adpcm(opensles->dsp_context,
buffer.b, rc, opensles->channels, opensles->block_size);
if (!opensles->dsp_context->encode_ms_adpcm(opensles->dsp_context,
buffer.b, rc, opensles->channels, opensles->block_size))
{
error = ERROR_INTERNAL_ERROR;
break;
}
encoded_data = opensles->dsp_context->adpcm_buffer;
encoded_size = opensles->dsp_context->adpcm_size;
}
else if (opensles->format == WAVE_FORMAT_DVI_ADPCM)
{
opensles->dsp_context->encode_ima_adpcm(opensles->dsp_context,
if (!opensles->dsp_context->encode_ima_adpcm(opensles->dsp_context,
buffer.b, rc,
opensles->channels, opensles->block_size);
opensles->channels, opensles->block_size))
{
error = ERROR_INTERNAL_ERROR;
break;
}
encoded_data = opensles->dsp_context->adpcm_buffer;
encoded_size = opensles->dsp_context->adpcm_size;
@ -135,8 +148,8 @@ static void* audin_opensles_thread_func(void* arg)
encoded_size = rc;
}
rc = opensles->receive(encoded_data, encoded_size, opensles->user_data);
if (rc)
error = opensles->receive(encoded_data, encoded_size, opensles->user_data);
if (error)
break;
}
@ -144,7 +157,10 @@ static void* audin_opensles_thread_func(void* arg)
DEBUG_DVC("thread shutdown.");
ExitThread((DWORD)rc);
if (error && opensles->rdpcontext)
setChannelError(opensles->rdpcontext, error, "audin_opensles_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -312,7 +328,6 @@ static WIN32ERROR audin_opensles_open(IAudinDevice* device, AudinReceive receive
WLog_ERR(TAG, "CreateEvent failed!");
goto error_out;
}
// TODO: add mechanism that threads can signal failure
if (!(opensles->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_opensles_thread_func,
opensles, 0, NULL)))
@ -441,6 +456,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(
opensles->iface.SetFormat = audin_opensles_set_format;
opensles->iface.Close = audin_opensles_close;
opensles->iface.Free = audin_opensles_free;
opensles->rdpcontext = pEntryPoints->rdpcontext;
args = pEntryPoints->args;

View File

@ -66,6 +66,8 @@ typedef struct _AudinOSSDevice {
AudinReceive receive;
void* user_data;
rdpContext* rdpcontext;
} AudinOSSDevice;
#define OSS_LOG_ERR(_text, _error) \
@ -156,13 +158,17 @@ static void *audin_oss_thread_func(void *arg)
WIN32ERROR error;
if (arg == NULL)
{
error = ERROR_INVALID_PARAMETER;
goto err_out;
}
if (oss->dev_unit != -1)
snprintf(dev_name, (PATH_MAX - 1), "/dev/dsp%i", oss->dev_unit);
WLog_INFO(TAG, "open: %s", dev_name);
if ((pcm_handle = open(dev_name, O_RDONLY)) < 0) {
OSS_LOG_ERR("sound dev open failed", errno);
error = (WIN32ERROR)errno;
goto err_out;
}
#if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_INPUT flag. */
@ -192,6 +198,7 @@ static void *audin_oss_thread_func(void *arg)
buffer = (BYTE*)calloc(1, (buffer_size + sizeof(void*)));
if (NULL == buffer) {
OSS_LOG_ERR("malloc() fail", errno);
error = ERROR_NOT_ENOUGH_MEMORY;
goto err_out;
}
@ -208,14 +215,22 @@ static void *audin_oss_thread_func(void *arg)
/* Process. */
switch (oss->format.wFormatTag) {
case WAVE_FORMAT_ADPCM:
oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign);
if (!oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
{
error = ERROR_INTERNAL_ERROR;
break;
}
encoded_data = oss->dsp_context->adpcm_buffer;
encoded_size = oss->dsp_context->adpcm_size;
break;
case WAVE_FORMAT_DVI_ADPCM:
oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign);
if (!oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
{
error = ERROR_INTERNAL_ERROR;
break;
}
encoded_data = oss->dsp_context->adpcm_buffer;
encoded_size = oss->dsp_context->adpcm_size;
break;
@ -233,6 +248,10 @@ static void *audin_oss_thread_func(void *arg)
}
err_out:
if (error && oss->rdpcontext)
setChannelError(oss->rdpcontext, error, "audin_oss_thread_func reported an error");
if (pcm_handle != -1)
close(pcm_handle);
free(buffer);
@ -253,7 +272,6 @@ static WIN32ERROR audin_oss_open(IAudinDevice *device, AudinReceive receive, voi
WLog_ERR(TAG, "CreateEvent failed!");
return ERROR_INTERNAL_ERROR;
}
// TODO: add mechanism that threads can signal failure
if (!(oss->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL)))
{
@ -374,6 +392,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POIN
oss->iface.SetFormat = audin_oss_set_format;
oss->iface.Close = audin_oss_close;
oss->iface.Free = audin_oss_free;
oss->rdpcontext = pEntryPoints->rdpcontext;
oss->dev_unit = -1;

View File

@ -36,6 +36,7 @@
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/client/audin.h>
#include "audin_main.h"
@ -60,6 +61,8 @@ typedef struct _AudinPulseDevice
AudinReceive receive;
void* user_data;
rdpContext* rdpcontext;
} AudinPulseDevice;
static void audin_pulse_context_state_callback(pa_context* context, void* userdata)
@ -280,12 +283,12 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length
{
int frames;
int cframes;
BOOL ret;
const void* data;
const BYTE* src;
int encoded_size;
BYTE* encoded_data;
AudinPulseDevice* pulse = (AudinPulseDevice*) userdata;
WIN32ERROR error = CHANNEL_RC_OK;
/* There is a race condition here where we may receive this callback
* before the buffer has been set up in the main code. It's probably
@ -316,9 +319,13 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length
{
if (pulse->format == 0x11)
{
pulse->dsp_context->encode_ima_adpcm(pulse->dsp_context,
if (!pulse->dsp_context->encode_ima_adpcm(pulse->dsp_context,
pulse->buffer, pulse->buffer_frames * pulse->bytes_per_frame,
pulse->sample_spec.channels, pulse->block_size);
pulse->sample_spec.channels, pulse->block_size))
{
error = ERROR_INTERNAL_ERROR;
break;
}
encoded_data = pulse->dsp_context->adpcm_buffer;
encoded_size = pulse->dsp_context->adpcm_size;
}
@ -331,9 +338,9 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length
DEBUG_DVC("encoded %d [%d] to %d [%X]",
pulse->buffer_frames, pulse->bytes_per_frame, encoded_size,
pulse->format);
ret = pulse->receive(encoded_data, encoded_size, pulse->user_data);
error = pulse->receive(encoded_data, encoded_size, pulse->user_data);
pulse->buffer_frames = 0;
if (!ret)
if (!error)
break;
}
src += cframes * pulse->bytes_per_frame;
@ -341,6 +348,9 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length
}
pa_stream_drop(stream);
if (error && pulse->rdpcontext)
setChannelError(pulse->rdpcontext, error, "audin_oss_thread_func reported an error");
}
@ -434,7 +444,7 @@ static WIN32ERROR audin_pulse_open(IAudinDevice* device, AudinReceive receive, v
pulse->buffer = calloc(1, pulse->bytes_per_frame * pulse->frames_per_packet);
if (!pulse->buffer) {
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_OK;
return CHANNEL_RC_NO_MEMORY;
}
pulse->buffer_frames = 0;
DEBUG_DVC("connected");
@ -506,6 +516,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POIN
pulse->iface.SetFormat = audin_pulse_set_format;
pulse->iface.Close = audin_pulse_close;
pulse->iface.Free = audin_pulse_free;
pulse->rdpcontext = pEntryPoints->rdpcontext;
args = pEntryPoints->args;

View File

@ -33,6 +33,7 @@
#include <winpr/crt.h>
#include <winpr/cmdline.h>
#include <freerdp/addin.h>
#include <freerdp/client/audin.h>
#include "audin_main.h"
@ -51,6 +52,7 @@ typedef struct _AudinWinmmDevice
UINT32 ppwfx_size;
UINT32 cFormats;
UINT32 frames_per_packet;
rdpContext* rdpcontext;
} AudinWinmmDevice;
static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance,
@ -58,6 +60,8 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) dwInstance;
PWAVEHDR pWaveHdr;
WIN32ERROR error = CHANNEL_RC_OK;
MMRESULT mmResult;
switch(uMsg)
{
@ -71,8 +75,11 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance
if (pWaveHdr->dwBytesRecorded
&& !(WaitForSingleObject(winmm->stopEvent, 0) == WAIT_OBJECT_0))
{
winmm->receive(pWaveHdr->lpData, pWaveHdr->dwBytesRecorded, winmm->user_data);
waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
if ((error = winmm->receive(pWaveHdr->lpData, pWaveHdr->dwBytesRecorded, winmm->user_data)))
break;
mmResult = waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
if (mmResult != MMSYSERR_NOERROR)
error = ERROR_INTERNAL_ERROR;
}
}
break;
@ -83,6 +90,8 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance
default:
break;
}
if (error && winmm->rdpcontext)
setChannelError(winmm->rdpcontext, error, "waveInProc reported an error");
}
static DWORD audin_winmm_thread_func(void* arg)
@ -97,6 +106,8 @@ static DWORD audin_winmm_thread_func(void* arg)
if (MMSYSERR_NOERROR != waveInOpen(&winmm->hWaveIn, WAVE_MAPPER, winmm->pwfx_cur,
(DWORD_PTR)waveInProc, (DWORD_PTR)winmm, CALLBACK_FUNCTION))
{
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, "audin_winmm_thread_func reported an error");
return 0;
}
}
@ -113,10 +124,14 @@ static DWORD audin_winmm_thread_func(void* arg)
if (MMSYSERR_NOERROR != waveInPrepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
{
DEBUG_DVC("waveInPrepareHeader failed.");
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, "audin_winmm_thread_func reported an error");
}
if (MMSYSERR_NOERROR != waveInAddBuffer(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
{
DEBUG_DVC("waveInAddBuffer failed.");
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, "audin_winmm_thread_func reported an error");
}
}
waveInStart(winmm->hWaveIn);
@ -130,6 +145,8 @@ static DWORD audin_winmm_thread_func(void* arg)
if (MMSYSERR_NOERROR != waveInUnprepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
{
DEBUG_DVC("waveInUnprepareHeader failed.");
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, "audin_winmm_thread_func reported an error");
}
free(waveHdr[i].lpData);
}
@ -252,7 +269,7 @@ static WIN32ERROR audin_winmm_open(IAudinDevice* device, AudinReceive receive, v
WLog_ERR(TAG, "CreateEvent failed!");
return ERROR_INTERNAL_ERROR;
}
// TODO: add mechanism that threads can signal failure
if (!(winmm->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL)))
{
@ -329,6 +346,7 @@ WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POIN
winmm->iface.SetFormat = audin_winmm_set_format;
winmm->iface.Close = audin_winmm_close;
winmm->iface.Free = audin_winmm_free;
winmm->rdpcontext = pEntryPoints->rdpcontext;
args = pEntryPoints->args;

View File

@ -497,6 +497,9 @@ out_capacity:
out:
WTSVirtualChannelClose(audin->audin_channel);
audin->audin_channel = NULL;
if (error && audin->context.rdpcontext)
setChannelError(audin->context.rdpcontext, error, "audin_server_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -534,7 +537,6 @@ static BOOL audin_server_open(audin_server_context* context)
return FALSE;
}
// TODO: implement signaling an error
if (!(audin->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL)))
{

View File

@ -968,7 +968,11 @@ static WIN32ERROR cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cli
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(cliprdr->queue, NULL, 0, (void*) data_in, NULL);
if (!MessageQueue_Post(cliprdr->queue, NULL, 0, (void*) data_in, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
}
return CHANNEL_RC_OK;
}
@ -977,21 +981,20 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle, UINT
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
cliprdrPlugin* cliprdr;
WIN32ERROR error = CHANNEL_RC_OK;
cliprdr = (cliprdrPlugin*) cliprdr_get_open_handle_data(openHandle);
if (!cliprdr)
{
WLog_ERR(TAG, "cliprdr_virtual_channel_open_event: error no match");
cliprdr->error = CHANNEL_RC_BAD_CHANNEL;
return;
}
cliprdr->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
cliprdr->error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength, totalLength, dataFlags);
error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength, totalLength, dataFlags);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
@ -1001,7 +1004,10 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle, UINT
case CHANNEL_EVENT_USER:
break;
}
//TODO report error
if (error && cliprdr->context->rdpcontext)
setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_open_event reported an error");
}
static void* cliprdr_virtual_channel_client_thread(void* arg)
@ -1014,25 +1020,35 @@ static void* cliprdr_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(cliprdr->queue))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (!MessageQueue_Peek(cliprdr->queue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
if (MessageQueue_Peek(cliprdr->queue, &message, TRUE))
if (message.id == 0)
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
data = (wStream*) message.wParam;
if ((error = cliprdr_order_recv(cliprdr, data)))
{
data = (wStream*) message.wParam;
if ((error = cliprdr_order_recv(cliprdr, data)))
{
WLog_ERR(TAG, "cliprdr_order_recv failed with error %lu!", error);
break;
}
WLog_ERR(TAG, "cliprdr_order_recv failed with error %lu!", error);
break;
}
}
}
if (error && cliprdr->context->rdpcontext)
setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -1115,37 +1131,36 @@ static WIN32ERROR cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprd
static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
cliprdrPlugin* cliprdr;
WIN32ERROR error = CHANNEL_RC_OK;
cliprdr = (cliprdrPlugin*) cliprdr_get_init_handle_data(pInitHandle);
if (!cliprdr)
{
WLog_ERR(TAG, "cliprdr_virtual_channel_init_event: error no match");
cliprdr->error = CHANNEL_RC_BAD_CHANNEL;
WLog_ERR(TAG, "error no match");
return;
}
cliprdr->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
if ((cliprdr->error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength)))
WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %lu!", cliprdr->error);
if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength)))
WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %lu!", error);
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((cliprdr->error = cliprdr_virtual_channel_event_disconnected(cliprdr)))
WLog_ERR(TAG, "cliprdr_virtual_channel_event_disconnected failed with error %lu!", cliprdr->error);
if ((error = cliprdr_virtual_channel_event_disconnected(cliprdr)))
WLog_ERR(TAG, "cliprdr_virtual_channel_event_disconnected failed with error %lu!", error);
break;
case CHANNEL_EVENT_TERMINATED:
if ((cliprdr->error = cliprdr_virtual_channel_event_terminated(cliprdr)))
WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %lu!", cliprdr->error);
if ((error = cliprdr_virtual_channel_event_terminated(cliprdr)))
WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %lu!", error);
break;
}
// to satisfy compiler
// TODO report error!!!
if (error && cliprdr->context->rdpcontext)
setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_init_event reported an error");
return;
}
@ -1205,6 +1220,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
*(pEntryPointsEx->ppInterface) = (void*) context;
cliprdr->context = context;
context->rdpcontext = pEntryPointsEx->context;
}
cliprdr->log = WLog_Get("com.freerdp.channels.cliprdr.client");

View File

@ -50,7 +50,6 @@ struct cliprdr_plugin
BOOL streamFileClipEnabled;
BOOL fileClipNoFilePaths;
BOOL canLockClipData;
WIN32ERROR error;
};
typedef struct cliprdr_plugin cliprdrPlugin;

View File

@ -1147,8 +1147,7 @@ static void* cliprdr_server_thread(void* arg)
if ((error = cliprdr_server_init(context)))
{
WLog_ERR(TAG, "cliprdr_server_init failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
goto out;
}
while (1)
@ -1156,9 +1155,7 @@ static void* cliprdr_server_thread(void* arg)
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(cliprdr->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
{
@ -1169,6 +1166,10 @@ static void* cliprdr_server_thread(void* arg)
}
}
}
out:
if (error && context->rdpcontext)
setChannelError(context->rdpcontext, error, "cliprdr_server_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -1250,7 +1251,6 @@ static WIN32ERROR cliprdr_server_start(CliprdrServerContext* context)
return ERROR_INTERNAL_ERROR;
}
// TODO: add mechanism that threads can signal failure
if (!(cliprdr->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL)))
{

View File

@ -659,14 +659,10 @@ WIN32ERROR drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* da
WLog_DBG(TAG, "write_data: ChannelId=%d size=%d", ChannelId, dataSize);
if (drdynvc->channel_error != CHANNEL_RC_OK)
return drdynvc->channel_error;
data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH);
if (!data_out)
{
drdynvc->channel_error = CHANNEL_RC_NO_MEMORY;
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -716,7 +712,6 @@ WIN32ERROR drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* da
data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH);
if (!data_out)
{
drdynvc->channel_error = CHANNEL_RC_NO_MEMORY;
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -745,7 +740,6 @@ WIN32ERROR drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* da
if (status != CHANNEL_RC_OK)
{
drdynvc->channel_error = status;
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
return status;
@ -804,8 +798,6 @@ static WIN32ERROR drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int
status = drdynvc_send_capability_response(drdynvc);
drdynvc->channel_error = status;
drdynvc->state = DRDYNVC_STATE_READY;
return status;
@ -973,8 +965,6 @@ static WIN32ERROR drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
error = drdynvc_send(drdynvc, data_out);
drdynvc->channel_error = error;
if (error)
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(error), error);
@ -1155,7 +1145,11 @@ static WIN32ERROR drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drd
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL);
if (!MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
}
return CHANNEL_RC_OK;
}
@ -1164,22 +1158,21 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle, UINT
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
drdynvcPlugin* drdynvc;
WIN32ERROR error = CHANNEL_RC_OK;
drdynvc = (drdynvcPlugin*) drdynvc_get_open_handle_data(openHandle);
if (!drdynvc)
{
WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match");
drdynvc->channel_error = CHANNEL_RC_BAD_CHANNEL;
return;
}
drdynvc->channel_error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
drdynvc->channel_error = drdynvc_virtual_channel_event_data_received(drdynvc, pData, dataLength, totalLength, dataFlags);
return;
if ((error = drdynvc_virtual_channel_event_data_received(drdynvc, pData, dataLength, totalLength, dataFlags)))
WLog_ERR(TAG, "drdynvc_virtual_channel_event_data_received failed with error %lu", error);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
@ -1189,7 +1182,9 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle, UINT
case CHANNEL_EVENT_USER:
break;
}
//TODO signal error
if (error && drdynvc->rdpcontext)
setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_open_event reported an error");
}
static void* drdynvc_virtual_channel_client_thread(void* arg)
@ -1202,28 +1197,37 @@ static void* drdynvc_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(drdynvc->queue))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (!MessageQueue_Peek(drdynvc->queue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
if (MessageQueue_Peek(drdynvc->queue, &message, TRUE))
if (message.id == 0)
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
data = (wStream*) message.wParam;
if ((error = drdynvc_order_recv(drdynvc, data)))
{
data = (wStream*) message.wParam;
if ((error = drdynvc_order_recv(drdynvc, data)))
{
Stream_Free(data, TRUE);
WLog_ERR(TAG, "drdynvc_order_recv failed with error %lu!", error);
ExitThread((DWORD) error);
return NULL;
}
Stream_Free(data, TRUE);
WLog_ERR(TAG, "drdynvc_order_recv failed with error %lu!", error);
break;
}
Stream_Free(data, TRUE);
}
}
if (error && drdynvc->rdpcontext)
setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_client_thread reported an error");
ExitThread((DWORD) error);
return NULL;
}
@ -1252,7 +1256,6 @@ static WIN32ERROR drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc
return error;
}
drdynvc->queue = MessageQueue_New(NULL);
if (!drdynvc->queue)
{
@ -1268,7 +1271,6 @@ static WIN32ERROR drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc
WLog_ERR(TAG, "dvcman_new failed!");
goto error;
}
drdynvc->channel_error = CHANNEL_RC_OK;
settings = (rdpSettings*) drdynvc->channelEntryPoints.pExtendedData;
@ -1294,6 +1296,8 @@ static WIN32ERROR drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc
goto error;
}
return CHANNEL_RC_OK;
error:
drdynvc_remove_open_handle_data(drdynvc->OpenHandle);
MessageQueue_Free(drdynvc->queue);
@ -1348,36 +1352,36 @@ static WIN32ERROR drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynv
static void VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
drdynvcPlugin* drdynvc;
WIN32ERROR error = CHANNEL_RC_OK;
drdynvc = (drdynvcPlugin*) drdynvc_get_init_handle_data(pInitHandle);
if (!drdynvc)
{
WLog_ERR(TAG, "drdynvc_virtual_channel_init_event: error no match");
drdynvc->channel_error = CHANNEL_RC_BAD_CHANNEL;
return;
}
drdynvc->channel_error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
drdynvc->channel_error = drdynvc_virtual_channel_event_connected(drdynvc, pData, dataLength);
return ;
if ((error = drdynvc_virtual_channel_event_connected(drdynvc, pData, dataLength)))
WLog_ERR(TAG, "drdynvc_virtual_channel_event_connected failed with error %lu", error);
break;
case CHANNEL_EVENT_DISCONNECTED:
drdynvc->channel_error = drdynvc_virtual_channel_event_disconnected(drdynvc);
return;
if ((error = drdynvc_virtual_channel_event_disconnected(drdynvc)))
WLog_ERR(TAG, "drdynvc_virtual_channel_event_disconnected failed with error %lu", error);
break;
case CHANNEL_EVENT_TERMINATED:
drdynvc->channel_error = drdynvc_virtual_channel_event_terminated(drdynvc);
return;
if ((error = drdynvc_virtual_channel_event_terminated(drdynvc)))
WLog_ERR(TAG, "drdynvc_virtual_channel_event_terminated failed with error %lu", error);
break;
}
//TODO signal error
if (error && drdynvc->rdpcontext)
setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_init_event reported an error");
}
/**
@ -1438,6 +1442,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
drdynvc->context = context;
context->GetVersion = drdynvc_get_version;
drdynvc->rdpcontext = pEntryPointsEx->context;
*(pEntryPointsEx->ppInterface) = (void*) context;
}

View File

@ -34,6 +34,7 @@
#include <freerdp/addin.h>
#include <freerdp/channels/log.h>
#include <freerdp/client/drdynvc.h>
#include <freerdp/freerdp.h>
typedef struct drdynvc_plugin drdynvcPlugin;
@ -132,7 +133,8 @@ struct drdynvc_plugin
int PriorityCharge1;
int PriorityCharge2;
int PriorityCharge3;
WIN32ERROR channel_error;
rdpContext* rdpcontext;
IWTSVirtualChannelManager* channel_mgr;
};

View File

@ -108,7 +108,7 @@ static void* drdynvc_server_thread(void* arg)
Stream_Free(s, TRUE);
ExitThread((DWORD) error);
#endif
// WTF ... this code only reads the stream till the stream has no place any more and then exits
// WTF ... this code only reads data into the stream until there is no more memory
ExitThread(0);
return NULL;
}
@ -128,8 +128,6 @@ static WIN32ERROR drdynvc_server_start(DrdynvcServerContext* context)
WLog_ERR(TAG, "CreateEvent failed!");
return ERROR_INTERNAL_ERROR;
}
// TODO: add mechanism that threads can signal failure
if (!(context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL)))
{

View File

@ -61,6 +61,8 @@ struct _DRIVE_DEVICE
wMessageQueue* IrpQueue;
DEVMAN* devman;
rdpContext* rdpcontext;
};
static UINT32 drive_map_posix_err(int fs_errno)
@ -619,15 +621,23 @@ static void* drive_thread_func(void* arg)
IRP* irp;
wMessage message;
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg;
WIN32ERROR error;
WIN32ERROR error = CHANNEL_RC_OK;
while (1)
{
if (!MessageQueue_Wait(drive->IrpQueue))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
@ -638,19 +648,24 @@ static void* drive_thread_func(void* arg)
if ((error = drive_process_irp(drive, irp)))
{
WLog_ERR(TAG, "drive_process_irp failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
break;
}
}
ExitThread(0);
if (error && drive->rdpcontext)
setChannelError(drive->rdpcontext, error, "drive_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
}
static WIN32ERROR drive_irp_request(DEVICE* device, IRP* irp)
{
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL);
if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
@ -704,6 +719,7 @@ WIN32ERROR drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
drive->device.name = name;
drive->device.IRPRequest = drive_irp_request;
drive->device.Free = drive_free;
drive->rdpcontext = pEntryPoints->rdpcontext;
length = (int) strlen(name);
drive->device.data = Stream_New(NULL, length + 1);

View File

@ -111,8 +111,7 @@ static void* echo_server_thread_func(void* arg)
{
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
goto out;
}
buffer = NULL;
@ -205,10 +204,13 @@ static void* echo_server_thread_func(void* arg)
break;
}
}
Stream_Free(s, TRUE);
WTSVirtualChannelClose(echo->echo_channel);
echo->echo_channel = NULL;
out:
if (error && echo->context.rdpcontext)
setChannelError(echo->context.rdpcontext, error, "echo_server_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
}

View File

@ -974,7 +974,11 @@ static WIN32ERROR encomsp_virtual_channel_event_data_received(encomspPlugin* enc
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(encomsp->queue, NULL, 0, (void*) data_in, NULL);
if (!MessageQueue_Post(encomsp->queue, NULL, 0, (void*) data_in, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
}
return CHANNEL_RC_OK;
}
@ -983,26 +987,21 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
encomspPlugin* encomsp;
WIN32ERROR error = CHANNEL_RC_OK;
encomsp = (encomspPlugin*) encomsp_get_open_handle_data(openHandle);
if (!encomsp)
{
WLog_ERR(TAG, "encomsp_virtual_channel_open_event: error no match");
encomsp->error = CHANNEL_RC_BAD_CHANNEL;
return;
}
encomsp->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
if ((encomsp->error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, totalLength, dataFlags)))
{
WLog_ERR(TAG, "encomsp_virtual_channel_event_data_received failed with error %lu", encomsp->error);
return;
}
if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, totalLength, dataFlags)))
WLog_ERR(TAG, "encomsp_virtual_channel_event_data_received failed with error %lu", error);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
@ -1012,8 +1011,10 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT
case CHANNEL_EVENT_USER:
break;
}
if (error && encomsp->rdpcontext)
setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_open_event reported an error");
return;
//TODO erport error
}
static void* encomsp_virtual_channel_client_thread(void* arg)
@ -1028,25 +1029,36 @@ static void* encomsp_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(encomsp->queue))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (!MessageQueue_Peek(encomsp->queue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
if (MessageQueue_Peek(encomsp->queue, &message, TRUE))
if (message.id == 0)
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
data = (wStream*) message.wParam;
if ((error = encomsp_process_receive(encomsp, data)))
{
data = (wStream*) message.wParam;
if ((error = encomsp_process_receive(encomsp, data)))
{
WLog_ERR(TAG, "encomsp_process_receive failed with error %lu!", error);
break;
}
WLog_ERR(TAG, "encomsp_process_receive failed with error %lu!", error);
break;
}
}
}
if (error && encomsp->rdpcontext)
setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -1131,34 +1143,26 @@ static WIN32ERROR encomsp_virtual_channel_event_terminated(encomspPlugin* encoms
static void VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
encomspPlugin* encomsp;
WIN32ERROR error = CHANNEL_RC_OK;
encomsp = (encomspPlugin*) encomsp_get_init_handle_data(pInitHandle);
if (!encomsp)
{
WLog_ERR(TAG, "encomsp_virtual_channel_init_event: error no match");
encomsp->error = CHANNEL_RC_BAD_CHANNEL;
return;
}
encomsp->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
if ((encomsp->error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength)))
{
WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu", encomsp->error);
return;
}
if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength)))
WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu", error);
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((encomsp->error = encomsp_virtual_channel_event_disconnected(encomsp)))
{
WLog_ERR(TAG, "encomsp_virtual_channel_event_disconnected failed with error %lu", encomsp->error);
return;
}
if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
WLog_ERR(TAG, "encomsp_virtual_channel_event_disconnected failed with error %lu", error);
break;
case CHANNEL_EVENT_TERMINATED:
@ -1166,11 +1170,13 @@ static void VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UIN
break;
default:
WLog_ERR(TAG, "uknown event type %d", event);
encomsp->error = ERROR_INVALID_DATA;
return;
error = ERROR_INVALID_DATA;
}
if (error && encomsp->rdpcontext)
setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_init_event reported an error");
return;
//TODO report error
}
/* encomsp is always built-in */
@ -1183,6 +1189,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
EncomspClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
BOOL isFreerdp = FALSE;
WIN32ERROR error;
encomsp = (encomspPlugin*) calloc(1, sizeof(encomspPlugin));
if (!encomsp)
@ -1227,6 +1234,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
*(pEntryPointsEx->ppInterface) = (void*) context;
encomsp->context = context;
encomsp->rdpcontext = pEntryPointsEx->context;
isFreerdp = TRUE;
}
@ -1244,9 +1252,9 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
encomsp->channelEntryPoints.pInterface = *(encomsp->channelEntryPoints.ppInterface);
encomsp->channelEntryPoints.ppInterface = &(encomsp->channelEntryPoints.pInterface);
if ((encomsp->error = encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp)))
if ((error = encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp)))
{
WLog_ERR(TAG, "encomsp_add_init_handle_data failed with error %lu!", encomsp->error);
WLog_ERR(TAG, "encomsp_add_init_handle_data failed with error %lu!", error);
goto error_out;
}

View File

@ -49,7 +49,7 @@ struct encomsp_plugin
void* InitHandle;
DWORD OpenHandle;
wMessageQueue* queue;
WIN32ERROR error;
rdpContext* rdpcontext;
};
typedef struct encomsp_plugin encomspPlugin;

View File

@ -179,8 +179,8 @@ static void* encomsp_server_thread(void* arg)
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
ExitThread((DWORD) CHANNEL_RC_NO_MEMORY);
return NULL;
error = CHANNEL_RC_NO_MEMORY;
goto out;
}
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
@ -240,6 +240,10 @@ static void* encomsp_server_thread(void* arg)
}
Stream_Free(s, TRUE);
out:
if (error && context->rdpcontext)
setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}

View File

@ -70,6 +70,7 @@ struct _PARALLEL_DEVICE
HANDLE thread;
wMessageQueue* queue;
rdpContext* rdpcontext;
};
typedef struct _PARALLEL_DEVICE PARALLEL_DEVICE;
@ -224,7 +225,7 @@ static WIN32ERROR parallel_process_irp_device_control(PARALLEL_DEVICE* parallel,
return irp->Complete(irp);
}
static int parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
static WIN32ERROR parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
{
WIN32ERROR error;
@ -312,6 +313,9 @@ static void* parallel_thread_func(void* arg)
break;
}
}
if (error && parallel->rdpcontext)
setChannelError(parallel->rdpcontext, error, "parallel_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -320,7 +324,11 @@ static WIN32ERROR parallel_irp_request(DEVICE* device, IRP* irp)
{
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device;
MessageQueue_Post(parallel->queue, NULL, 0, (void*) irp, NULL);
if (!MessageQueue_Post(parallel->queue, NULL, 0, (void*) irp, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
@ -375,6 +383,7 @@ WIN32ERROR DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
parallel->device.name = name;
parallel->device.IRPRequest = parallel_irp_request;
parallel->device.Free = parallel_free;
parallel->rdpcontext = pEntryPoints->rdpcontext;
length = strlen(name);
parallel->device.data = Stream_New(NULL, length + 1);

View File

@ -62,6 +62,7 @@ struct _PRINTER_DEVICE
HANDLE stopEvent;
HANDLE thread;
rdpContext* rdpcontext;
};
static WIN32ERROR printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp)
@ -225,6 +226,8 @@ static void* printer_thread_func(void* arg)
break;
}
}
if (error && printer_dev->rdpcontext)
setChannelError(printer_dev->rdpcontext, error, "printer_thread_func reported an error");
ExitThread((DWORD) error);
@ -299,6 +302,7 @@ WIN32ERROR printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinte
printer_dev->device.name = port;
printer_dev->device.IRPRequest = printer_irp_request;
printer_dev->device.Free = printer_free;
printer_dev->rdpcontext = pEntryPoints->rdpcontext;
printer_dev->printer = printer;

View File

@ -401,7 +401,7 @@ WIN32ERROR rail_add_open_handle_data(DWORD openHandle, void* pUserData)
return CHANNEL_RC_NO_MEMORY;
}
ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData);
if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData))
{
WLog_ERR(TAG, "ListDictionary_Add failed!");
return ERROR_INTERNAL_ERROR;
@ -471,7 +471,11 @@ static WIN32ERROR rail_virtual_channel_event_data_received(railPlugin* rail,
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(rail->queue, NULL, 0, (void*) data_in, NULL);
if (!MessageQueue_Post(rail->queue, NULL, 0, (void*) data_in, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
}
return CHANNEL_RC_OK;
}
@ -480,25 +484,21 @@ static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle, UINT eve
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
railPlugin* rail;
WIN32ERROR error = CHANNEL_RC_OK;
rail = (railPlugin*) rail_get_open_handle_data(openHandle);
if (!rail)
{
WLog_ERR(TAG, "rail_virtual_channel_open_event: error no match");
rail->error = CHANNEL_RC_BAD_CHANNEL;
return;
}
rail->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
if ((rail->error = rail_virtual_channel_event_data_received(rail, pData, dataLength, totalLength, dataFlags)))
{
WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!", rail->error);
return;
}
if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength, totalLength, dataFlags)))
WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!", error);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
@ -508,8 +508,11 @@ static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle, UINT eve
case CHANNEL_EVENT_USER:
break;
}
if (error && rail->rdpcontext)
setChannelError(rail->rdpcontext, error, "rail_virtual_channel_open_event reported an error");
return;
//TODO report error
}
static void* rail_virtual_channel_client_thread(void* arg)
@ -522,25 +525,35 @@ static void* rail_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(rail->queue))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (!MessageQueue_Peek(rail->queue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
if (MessageQueue_Peek(rail->queue, &message, TRUE))
if (message.id == 0)
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
data = (wStream*) message.wParam;
if ((error = rail_order_recv(rail, data)))
{
data = (wStream*) message.wParam;
if ((error = rail_order_recv(rail, data)))
{
WLog_ERR(TAG, "rail_order_recv failed with error %d!", error);
break;
}
WLog_ERR(TAG, "rail_order_recv failed with error %d!", error);
break;
}
}
}
if (error && rail->rdpcontext)
setChannelError(rail->rdpcontext, error, "rail_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -620,24 +633,22 @@ static void rail_virtual_channel_event_terminated(railPlugin* rail)
static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
railPlugin* rail;
WIN32ERROR error = CHANNEL_RC_OK;
rail = (railPlugin*) rail_get_init_handle_data(pInitHandle);
if (!rail)
{
WLog_ERR(TAG, "rail_virtual_channel_init_event: error no match");
rail->error = CHANNEL_RC_BAD_CHANNEL;
return;
}
rail->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
if ((rail->error = rail_virtual_channel_event_connected(rail, pData, dataLength)))
if ((error = rail_virtual_channel_event_connected(rail, pData, dataLength)))
{
WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!", rail->error);
WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!", error);
return;
}
break;
@ -650,8 +661,11 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT e
rail_virtual_channel_event_terminated(rail);
break;
}
if(error && rail->rdpcontext)
setChannelError(rail->rdpcontext, error, "rail_virtual_channel_init_event reported an error");
return;
//TODO report error
}
/* rail is always built-in */
@ -717,6 +731,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
context->ServerExecuteResult = rail_server_execute_result;
context->ClientGetAppIdRequest = rail_client_get_appid_request;
context->ServerGetAppIdResponse = rail_server_get_appid_response;
rail->rdpcontext = pEntryPointsEx->context;
*(pEntryPointsEx->ppInterface) = (void*) context;
rail->context = context;

View File

@ -49,7 +49,7 @@ struct rail_plugin
void* InitHandle;
DWORD OpenHandle;
wMessageQueue* queue;
WIN32ERROR error;
rdpContext* rdpcontext;
};
typedef struct rail_plugin railPlugin;

View File

@ -120,7 +120,7 @@ static char SMARTCARD_SERVICE_NAME[] = "smartcard";
static char SERIAL_SERVICE_NAME[] = "serial";
static char PARALLEL_SERVICE_NAME[] = "parallel";
WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device)
WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext)
{
char* ServiceName = NULL;
DEVICE_SERVICE_ENTRY_POINTS ep;
@ -155,8 +155,7 @@ WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device)
ep.devman = devman;
ep.RegisterDevice = devman_register_device;
ep.device = device;
ep.rdpcontext = rdpcontext;
entry(&ep);
return CHANNEL_RC_OK;
return entry(&ep);
}

View File

@ -26,7 +26,7 @@
#include "rdpdr_main.h"
void devman_unregister_device(DEVMAN* devman, void* key);
WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device);
WIN32ERROR devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext);
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id);
DEVMAN* devman_new(rdpdrPlugin* rdpdr);

View File

@ -129,7 +129,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
drive->Path = _strdup(drive_path);
drive_path[1] = '\0';
drive->Name = _strdup(drive_path);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext);
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
}
unitmask = unitmask >> 1;
@ -464,7 +464,7 @@ static WIN32ERROR handle_hotplug(rdpdrPlugin* rdpdr)
free(drive);
return CHANNEL_RC_NO_MEMORY;
}
if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive)))
if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext)))
{
WLog_ERR(TAG, "devman_load_device_service failed!");
free(drive->Path);
@ -596,7 +596,7 @@ static WIN32ERROR rdpdr_process_connect(rdpdrPlugin* rdpdr)
continue;
}
if ((error = devman_load_device_service(rdpdr->devman, device)))
if ((error = devman_load_device_service(rdpdr->devman, device, rdpdr->rdpcontext)))
{
WLog_ERR(TAG, "devman_load_device_service failed with error %lu!", error);
return error;
@ -895,9 +895,9 @@ static WIN32ERROR rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
if ((error = rdpdr_process_irp(rdpdr, s)))
{
WLog_ERR(TAG, "rdpdr_process_irp failed with error %lu", error);
s = NULL;
return error;
}
s = NULL;
break;
default:
@ -1083,7 +1083,11 @@ static WIN32ERROR rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr,
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(rdpdr->queue, NULL, 0, (void*) data_in, NULL);
if (!MessageQueue_Post(rdpdr->queue, NULL, 0, (void*) data_in, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
}
return CHANNEL_RC_OK;
}
@ -1092,25 +1096,21 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT ev
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
rdpdrPlugin* rdpdr;
WIN32ERROR error = CHANNEL_RC_OK;
rdpdr = (rdpdrPlugin*) rdpdr_get_open_handle_data(openHandle);
if (!rdpdr)
{
WLog_ERR(TAG, "rdpdr_virtual_channel_open_event: error no match");
rdpdr->error = CHANNEL_RC_BAD_CHANNEL;
return;
}
rdpdr->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
if ((rdpdr->error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags)))
{
WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received failed with error %lu!", rdpdr->error );
return;
}
if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags)))
WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received failed with error %lu!", error );
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
@ -1120,8 +1120,10 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT ev
case CHANNEL_EVENT_USER:
break;
}
if (error && rdpdr->rdpcontext)
setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_open_event reported an error");
return;
//TODO report error
}
static void* rdpdr_virtual_channel_client_thread(void* arg)
@ -1129,11 +1131,13 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
wStream* data;
wMessage message;
rdpdrPlugin* rdpdr = (rdpdrPlugin*) arg;
int error;
WIN32ERROR error;
if ((error = rdpdr_process_connect(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_process_connect failed with error %lu!", error);
if (rdpdr->rdpcontext)
setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_client_thread reported an error");
ExitThread((DWORD) error);
return NULL;
}
@ -1154,6 +1158,8 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
if ((error = rdpdr_process_receive(rdpdr, data)))
{
WLog_ERR(TAG, "rdpdr_process_receive failed with error %lu!", error);
if (rdpdr->rdpcontext)
setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_client_thread reported an error");
ExitThread((DWORD) error);
return NULL;
}
@ -1250,34 +1256,28 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
rdpdrPlugin* rdpdr;
WIN32ERROR error = CHANNEL_RC_OK;
rdpdr = (rdpdrPlugin*) rdpdr_get_init_handle_data(pInitHandle);
if (!rdpdr)
{
WLog_ERR(TAG, "rdpdr_virtual_channel_init_event: error no match");
rdpdr->error = CHANNEL_RC_BAD_CHANNEL;
WLog_ERR(TAG, "error no match");
return;
}
rdpdr->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_INITIALIZED:
break;
case CHANNEL_EVENT_CONNECTED:
if ((rdpdr->error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength)))
{
WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!", rdpdr->error);
return;
}
if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength)))
WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!", error);
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((rdpdr->error = rdpdr_virtual_channel_event_disconnected(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!", rdpdr->error);
return;
}
if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr)))
WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!", error);
break;
case CHANNEL_EVENT_TERMINATED:
@ -1285,11 +1285,13 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT
break;
default:
WLog_ERR(TAG, "unknown event %d!", event);
rdpdr->error = ERROR_INVALID_DATA;
error = ERROR_INVALID_DATA;
break;
}
if (error && rdpdr->rdpcontext)
setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_init_event reported an error");
return;
//TODO report error
}
/* rdpdr is always built-in */
@ -1299,6 +1301,8 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
rdpdrPlugin* rdpdr;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
rdpdr = (rdpdrPlugin*) calloc(1, sizeof(rdpdrPlugin));
@ -1317,6 +1321,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
rdpdr->sequenceId = 0;
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
rdpdr->rdpcontext = pEntryPointsEx->context;
}
CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));

View File

@ -67,7 +67,7 @@ struct rdpdr_plugin
#else
HANDLE stopEvent;
#endif
WIN32ERROR error;
rdpContext* rdpcontext;
};
WIN32ERROR rdpdr_send(rdpdrPlugin* rdpdr, wStream* s);

View File

@ -947,8 +947,8 @@ static void* rdpdr_server_thread(void* arg)
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
ExitThread((DWORD) CHANNEL_RC_NO_MEMORY);
return NULL;
error = CHANNEL_RC_NO_MEMORY;
goto out;
}
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
@ -965,9 +965,7 @@ static void* rdpdr_server_thread(void* arg)
if ((error = rdpdr_server_send_announce_request(context)))
{
WLog_ERR(TAG, "rdpdr_server_send_announce_request failed with error %lu!", error);
Stream_Free(s, TRUE);
ExitThread((DWORD) error);
return NULL;
goto out_stream;
}
while (1)
@ -976,14 +974,13 @@ static void* rdpdr_server_thread(void* arg)
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
@ -1001,16 +998,18 @@ static void* rdpdr_server_thread(void* arg)
if ((error = rdpdr_server_receive_pdu(context, s, &header)))
{
WLog_ERR(TAG, "rdpdr_server_receive_pdu failed with error %lu!", error);
Stream_Free(s, TRUE);
ExitThread((DWORD) error);
return NULL;
goto out_stream;
}
}
}
}
out_stream:
Stream_Free(s, TRUE);
ExitThread((DWORD) CHANNEL_RC_OK);
out:
if (error && context->rdpcontext)
setChannelError(context->rdpcontext, error, "rdpdr_server_thread reported an error");
ExitThread((DWORD) error);
return NULL;
}

View File

@ -36,6 +36,7 @@
#include <winpr/collections.h>
#include <freerdp/addin.h>
#include <freerdp/freerdp.h>
#include "rdpei_common.h"
@ -105,6 +106,7 @@ struct _RDPEI_PLUGIN
HANDLE thread;
CRITICAL_SECTION lock;
rdpContext* rdpcontext;
};
typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN;
@ -162,19 +164,19 @@ static void* rdpei_schedule_thread(void* arg)
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg;
RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface;
HANDLE hdl[] = {rdpei->event, rdpei->stopEvent};
WIN32ERROR error;
WIN32ERROR error = CHANNEL_RC_OK;
if (!rdpei)
{
ExitThread((DWORD)ERROR_INVALID_PARAMETER);
return NULL;
error = ERROR_INVALID_PARAMETER;
goto out;
}
if (!context)
{
ExitThread((DWORD)ERROR_INVALID_PARAMETER);
return NULL;
error = ERROR_INVALID_PARAMETER;
goto out;
}
while (1)
@ -188,8 +190,7 @@ static void* rdpei_schedule_thread(void* arg)
if ((error = rdpei_add_frame(context)))
{
WLog_ERR(TAG, "rdpei_add_frame failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
break;
}
if (rdpei->frame.contactCount > 0)
@ -197,18 +198,20 @@ static void* rdpei_schedule_thread(void* arg)
if ((error = rdpei_send_frame(context)))
{
WLog_ERR(TAG, "rdpei_send_frame failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
break;
}
}
if (status == WAIT_OBJECT_0)
ResetEvent(rdpei->event);
LeaveCriticalSection(&rdpei->lock);
}
out:
if (error && rdpei->rdpcontext)
setChannelError(rdpei->rdpcontext, error, "rdpei_schedule_thread reported an error");
ExitThread(0);
return NULL;
@ -874,6 +877,10 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
rdpei->maxTouchContacts = 10;
size = rdpei->maxTouchContacts * sizeof(RDPINPUT_CONTACT_POINT);
rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*) calloc(1, size);
rdpei->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context;
if (!rdpei->contactPoints)
{
WLog_ERR(TAG, "calloc failed!");

View File

@ -1381,6 +1381,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext));
if (!context)

View File

@ -30,6 +30,7 @@
#include <freerdp/client/rdpgfx.h>
#include <freerdp/channels/log.h>
#include <freerdp/codec/zgfx.h>
#include <freerdp/freerdp.h>
#define TAG CHANNELS_TAG("rdpgfx.client")
@ -77,6 +78,7 @@ struct _RDPGFX_PLUGIN
UINT16 MaxCacheSlot;
void* CacheSlots[25600];
rdpContext* rdpcontext;
};
typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN;

View File

@ -4,6 +4,8 @@
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2010-2011 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -601,7 +603,7 @@ static COMMAND_LINE_ARGUMENT_A rdpsnd_alsa_args[] =
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
static WIN32ERROR rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
{
int status;
DWORD flags;
@ -612,7 +614,10 @@ static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV*
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_alsa_args, flags, alsa, NULL, NULL);
if (status < 0)
return status;
{
WLog_ERR(TAG, "CommandLineParseArgumentsA failed!");
return CHANNEL_RC_INITIALIZATION_ERROR;
}
arg = rdpsnd_alsa_args;
@ -634,21 +639,25 @@ static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV*
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
return status;
return CHANNEL_RC_OK;
}
#ifdef STATIC_CHANNELS
#define freerdp_rdpsnd_client_subsystem_entry alsa_freerdp_rdpsnd_client_subsystem_entry
#endif
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
{
ADDIN_ARGV* args;
rdpsndAlsaPlugin* alsa;
WIN32ERROR error;
alsa = (rdpsndAlsaPlugin*) calloc(1, sizeof(rdpsndAlsaPlugin));
if (!alsa)
return -1;
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
alsa->device.Open = rdpsnd_alsa_open;
alsa->device.FormatSupported = rdpsnd_alsa_format_supported;
@ -661,14 +670,22 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
alsa->device.Free = rdpsnd_alsa_free;
args = pEntryPoints->args;
if (rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin*) alsa, args) != 0)
if ((error = rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin*) alsa, args)))
{
WLog_ERR(TAG, "rdpsnd_alsa_parse_addin_args failed with error %lu", error);
goto error_parse_args;
}
if (!alsa->device_name)
{
alsa->device_name = _strdup("default");
if (!alsa->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_strdup;
}
}
alsa->pcm_handle = 0;
@ -681,11 +698,15 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
alsa->dsp_context = freerdp_dsp_context_new();
if (!alsa->dsp_context)
{
WLog_ERR(TAG, "freerdp_dsp_context_new failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_dsp_context;
}
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) alsa);
return 0;
return CHANNEL_RC_OK;
error_dsp_context:
free(alsa->device_name);
@ -693,5 +714,5 @@ error_strdup:
free(alsa->device_name);
error_parse_args:
free(alsa);
return -1;
return error;
}

View File

@ -3,6 +3,8 @@
* Audio Output Virtual Channel
*
* Copyright 2013 Dell Software <Mike.McDonald@software.dell.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,6 +27,7 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <winpr/win32error.h>
#import <AudioToolbox/AudioToolbox.h>
@ -281,12 +284,12 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device)
#define freerdp_rdpsnd_client_subsystem_entry ios_freerdp_rdpsnd_client_subsystem_entry
#endif
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
{
rdpsndIOSPlugin* p = (rdpsndIOSPlugin*) calloc(1, sizeof(rdpsndIOSPlugin));
if (!p)
return -1;
return CHANNEL_RC_NO_MEMORY;
p->device.Open = rdpsnd_ios_open;
p->device.FormatSupported = rdpsnd_ios_format_supported;
@ -299,5 +302,5 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p);
return 0;
return CHANNEL_RC_OK;
}

View File

@ -3,6 +3,8 @@
* Audio Output Virtual Channel
*
* Copyright 2012 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,6 +31,7 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <winpr/win32error.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioToolbox/AudioQueue.h>
@ -133,7 +136,7 @@ static BOOL rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
UInt32 DecodeBufferSizeFrames;
UInt32 propertySize = sizeof(DecodeBufferSizeFrames);
AudioQueueGetProperty(mac->audioQueue,
status = AudioQueueGetProperty(mac->audioQueue,
kAudioQueueProperty_DecodeBufferSizeFrames,
&DecodeBufferSizeFrames,
&propertySize);
@ -288,14 +291,14 @@ static void rdpsnd_mac_play(rdpsndDevicePlugin* device, BYTE* data, int size)
#define freerdp_rdpsnd_client_subsystem_entry mac_freerdp_rdpsnd_client_subsystem_entry
#endif
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
{
rdpsndMacPlugin* mac;
mac = (rdpsndMacPlugin*) calloc(1, sizeof(rdpsndMacPlugin));
if (!mac)
return -1;
return CHANNEL_RC_NO_MEMORY;
mac->device.Open = rdpsnd_mac_open;
mac->device.FormatSupported = rdpsnd_mac_format_supported;
@ -308,5 +311,5 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac);
return 0;
return CHANNEL_RC_OK;
}

View File

@ -3,6 +3,8 @@
* Audio Output Virtual Channel
*
* Copyright 2013 Armin Novak <armin.novak@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,6 +34,7 @@
#include <winpr/cmdline.h>
#include <winpr/sysinfo.h>
#include <winpr/collections.h>
#include <winpr/win32error.h>
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
@ -432,16 +435,18 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device,
opensles_freerdp_rdpsnd_client_subsystem_entry
#endif
int freerdp_rdpsnd_client_subsystem_entry(
WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(
PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
{
ADDIN_ARGV* args;
rdpsndopenslesPlugin* opensles;
WIN32ERROR error;
DEBUG_SND("pEntryPoints=%p", pEntryPoints);
opensles = (rdpsndopenslesPlugin*) malloc(sizeof(rdpsndopenslesPlugin));
ZeroMemory(opensles, sizeof(rdpsndopenslesPlugin));
opensles = (rdpsndopenslesPlugin*) calloc(1, sizeof(rdpsndopenslesPlugin));
if (!opensles)
return CHANNEL_RC_NO_MEMORY;
opensles->device.Open = rdpsnd_opensles_open;
opensles->device.FormatSupported = rdpsnd_opensles_format_supported;
@ -460,7 +465,10 @@ int freerdp_rdpsnd_client_subsystem_entry(
{
opensles->device_name = _strdup("default");
if (!opensles->device_name)
return ERROR_OUTOFMEMORY;
{
error = CHANNEL_RC_NO_MEMORY;
goto outstrdup;
}
}
opensles->rate = 44100;
@ -468,10 +476,20 @@ int freerdp_rdpsnd_client_subsystem_entry(
opensles->format = WAVE_FORMAT_ADPCM;
opensles->dsp_context = freerdp_dsp_context_new();
if (!opensles->dsp_context)
{
error = CHANNEL_RC_NO_MEMORY;
goto out_dsp_new;
}
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd,
(rdpsndDevicePlugin*) opensles);
DEBUG_SND("success");
return 0;
return CHANNEL_RC_OK;
out_dsp_new:
free(opensles->device_name);
outstrdup:
free(opensles);
return error;
}

View File

@ -3,6 +3,8 @@
* Audio Output Virtual Channel
*
* Copyright (c) 2015 Rozhuk Ivan <rozhuk.im@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -434,12 +436,13 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin *device, ADDIN_ARGV *a
#define freerdp_rdpsnd_client_subsystem_entry oss_freerdp_rdpsnd_client_subsystem_entry
#endif
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) {
WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) {
ADDIN_ARGV *args;
rdpsndOssPlugin *oss;
oss = (rdpsndOssPlugin*)malloc(sizeof(rdpsndOssPlugin));
ZeroMemory(oss, sizeof(rdpsndOssPlugin));
oss = (rdpsndOssPlugin*)calloc(1, sizeof(rdpsndOssPlugin));
if (!oss)
return CHANNEL_RC_NO_MEMORY;
oss->device.Open = rdpsnd_oss_open;
oss->device.FormatSupported = rdpsnd_oss_format_supported;
@ -459,8 +462,13 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
rdpsnd_oss_parse_addin_args((rdpsndDevicePlugin*)oss, args);
oss->dsp_context = freerdp_dsp_context_new();
if (!oss->dsp_context)
{
free(oss);
return CHANNEL_RC_NO_MEMORY;
}
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)oss);
return 0;
return CHANNEL_RC_OK;
}

View File

@ -3,6 +3,8 @@
* Audio Output Virtual Channel
*
* Copyright 2011 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -37,6 +39,7 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <winpr/win32error.h>
#include "rdpsnd_main.h"
@ -631,7 +634,7 @@ static WIN32ERROR rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDI
#define freerdp_rdpsnd_client_subsystem_entry pulse_freerdp_rdpsnd_client_subsystem_entry
#endif
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
{
ADDIN_ARGV* args;
rdpsndPulsePlugin* pulse;
@ -639,7 +642,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
pulse = (rdpsndPulsePlugin*) calloc(1, sizeof(rdpsndPulsePlugin));
if (!pulse)
return -1;
return CHANNEL_RC_NO_MEMORY;
pulse->device.Open = rdpsnd_pulse_open;
pulse->device.FormatSupported = rdpsnd_pulse_format_supported;
@ -658,7 +661,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
goto error;
}
ret = ERROR_OUTOFMEMORY;
ret = CHANNEL_RC_NO_MEMORY;
pulse->dsp_context = freerdp_dsp_context_new();
if (!pulse->dsp_context)
goto error;

View File

@ -5,6 +5,8 @@
* Copyright 2009-2011 Jay Sorg
* Copyright 2010-2011 Vic Lee
* Copyright 2012-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -93,6 +95,7 @@ struct rdpsnd_plugin
/* Device plugin */
rdpsndDevicePlugin* device;
rdpContext* rdpcontext;
};
static WIN32ERROR rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave);
@ -106,6 +109,7 @@ static void* rdpsnd_schedule_thread(void* arg)
RDPSND_WAVE* wave;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg;
HANDLE events[2];
WIN32ERROR error = CHANNEL_RC_OK;
events[0] = MessageQueue_Event(rdpsnd->MsgPipe->Out);
events[1] = rdpsnd->stopEvent;
@ -113,7 +117,11 @@ static void* rdpsnd_schedule_thread(void* arg)
while (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0)
{
if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
@ -128,18 +136,20 @@ static void* rdpsnd_schedule_thread(void* arg)
Sleep(wTimeDiff);
}
if (rdpsnd_confirm_wave(rdpsnd, wave) != CHANNEL_RC_OK)
if ((error = rdpsnd_confirm_wave(rdpsnd, wave)))
{
WLog_ERR(TAG, "error confirming wave");
break;
}
message.wParam = NULL;
free(wave);
}
ExitThread(0);
if (error && rdpsnd->rdpcontext)
setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_schedule_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -149,7 +159,10 @@ WIN32ERROR rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
pdu = Stream_New(NULL, 8);
if (!pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT8(pdu, SNDC_QUALITYMODE); /* msgType */
Stream_Write_UINT8(pdu, 0); /* bPad */
Stream_Write_UINT16(pdu, 4); /* BodySize */
@ -244,7 +257,10 @@ WIN32ERROR rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
pdu = Stream_New(NULL, length);
if (!pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT8(pdu, SNDC_FORMATS); /* msgType */
Stream_Write_UINT8(pdu, 0); /* bPad */
@ -370,7 +386,10 @@ WIN32ERROR rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeSt
pdu = Stream_New(NULL, 8);
if (!pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT8(pdu, SNDC_TRAINING); /* msgType */
Stream_Write_UINT8(pdu, 0); /* bPad */
@ -457,7 +476,10 @@ WIN32ERROR rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp,
pdu = Stream_New(NULL, 8);
if (!pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT8(pdu, SNDC_WAVECONFIRM);
Stream_Write_UINT8(pdu, 0);
@ -483,7 +505,10 @@ static WIN32ERROR rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device
return rdpsnd_confirm_wave(device->rdpsnd, wave);
if (!MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL))
return CHANNEL_RC_NO_MEMORY;
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
@ -511,9 +536,12 @@ static WIN32ERROR rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
data = Stream_Buffer(s);
size = (int) Stream_Capacity(s);
wave = (RDPSND_WAVE*) malloc(sizeof(RDPSND_WAVE));
wave = (RDPSND_WAVE*) calloc(1, sizeof(RDPSND_WAVE));
if (!wave)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
wave->wLocalTimeA = GetTickCount();
wave->wTimeStampA = rdpsnd->wTimeStamp;
@ -668,27 +696,25 @@ static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlug
device->WaveConfirm = rdpsnd_device_send_wave_confirm_pdu;
}
static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args)
static WIN32ERROR rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args)
{
PFREERDP_RDPSND_DEVICE_ENTRY entry;
FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;
FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;\
WIN32ERROR error;
entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0);
if (!entry)
return FALSE;
return ERROR_INTERNAL_ERROR;
entryPoints.rdpsnd = rdpsnd;
entryPoints.pRegisterRdpsndDevice = rdpsnd_register_device_plugin;
entryPoints.args = args;
if (entry(&entryPoints) != 0)
{
WLog_ERR(TAG, "%s entry returns error.", name);
return FALSE;
}
if ((error = entry(&entryPoints)))
WLog_ERR(TAG, "%s entry returns error %lu", name, error);
return TRUE;
return error;
}
BOOL rdpsnd_set_subsystem(rdpsndPlugin* rdpsnd, const char* subsystem)
@ -819,10 +845,10 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
if (strcmp(rdpsnd->subsystem, "fake") == 0)
return CHANNEL_RC_OK;
if (!rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args))
if ((status = rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args)))
{
WLog_ERR(TAG, "unable to load the %s subsystem plugin", rdpsnd->subsystem);
return CHANNEL_RC_INITIALIZATION_ERROR;
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
return status;
}
}
else
@ -832,7 +858,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
subsystem_name = "ios";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
{
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
return status;
}
}
#endif
@ -841,7 +871,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
subsystem_name = "opensles";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
{
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
return status;
}
}
#endif
@ -850,7 +884,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
subsystem_name = "pulse";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
{
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
return status;
}
}
#endif
@ -859,7 +897,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
subsystem_name = "alsa";
device_name = "default";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
{
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
return status;
}
}
#endif
@ -868,7 +910,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
subsystem_name = "oss";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
{
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
return status;
}
}
#endif
@ -878,7 +924,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
subsystem_name = "mac";
device_name = "default";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
{
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
return status;
}
}
#endif
@ -887,7 +937,11 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
subsystem_name = "winmm";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
{
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
return status;
}
}
#endif
@ -909,13 +963,19 @@ static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
rdpsnd->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!rdpsnd->stopEvent)
{
WLog_ERR(TAG, "CreateEvent failed!");
return CHANNEL_RC_INITIALIZATION_ERROR;
}
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
(void*) rdpsnd, 0, NULL);
if (!rdpsnd->ScheduleThread)
{
WLog_ERR(TAG, "CreateThread failed!");
return CHANNEL_RC_INITIALIZATION_ERROR;
}
}
return CHANNEL_RC_OK;
@ -1002,7 +1062,7 @@ void rdpsnd_remove_open_handle_data(DWORD openHandle)
WIN32ERROR rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
{
WIN32ERROR status = CHANNEL_RC_OK;
WIN32ERROR status;
if (!rdpsnd)
{
@ -1024,14 +1084,14 @@ WIN32ERROR rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
return status;
}
static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
static WIN32ERROR rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* s;
if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
{
return;
return CHANNEL_RC_OK;
}
if (dataFlags & CHANNEL_FLAG_FIRST)
@ -1040,10 +1100,21 @@ static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
Stream_Free(plugin->data_in, TRUE);
plugin->data_in = Stream_New(NULL, totalLength);
if (!plugin->data_in)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
}
s = plugin->data_in;
Stream_EnsureRemainingCapacity(s, (int) dataLength);
if (!Stream_EnsureRemainingCapacity(s, (int) dataLength))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write(s, pData, dataLength);
if (dataFlags & CHANNEL_FLAG_LAST)
@ -1051,20 +1122,27 @@ static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
if (Stream_Capacity(s) != Stream_GetPosition(s))
{
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_data_received: read error");
return ERROR_INTERNAL_ERROR;
}
plugin->data_in = NULL;
Stream_SealLength(s);
Stream_SetPosition(s, 0);
MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL);
if (!MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
}
return CHANNEL_RC_OK;
}
static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT event,
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
rdpsndPlugin* rdpsnd;
WIN32ERROR error = CHANNEL_RC_OK;
rdpsnd = (rdpsndPlugin*) rdpsnd_get_open_handle_data(openHandle);
@ -1077,7 +1155,8 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT e
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
rdpsnd_virtual_channel_event_data_received(rdpsnd, pData, dataLength, totalLength, dataFlags);
if ((error = rdpsnd_virtual_channel_event_data_received(rdpsnd, pData, dataLength, totalLength, dataFlags)))
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_data_received failed with error %lu", error);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
@ -1087,6 +1166,9 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT e
case CHANNEL_EVENT_USER:
break;
}
if (error && rdpsnd->rdpcontext)
setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_virtual_channel_open_event reported an error");
}
static void* rdpsnd_virtual_channel_client_thread(void* arg)
@ -1094,8 +1176,9 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg)
wStream* data;
wMessage message;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg;
WIN32ERROR error;
if (rdpsnd_process_connect(rdpsnd) != CHANNEL_RC_OK)
if ((error = rdpsnd_process_connect(rdpsnd)))
{
WLog_ERR(TAG, "error connecting sound channel");
goto out;
@ -1104,71 +1187,86 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(rdpsnd->MsgPipe->In))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (!MessageQueue_Peek(rdpsnd->MsgPipe->In, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
if (MessageQueue_Peek(rdpsnd->MsgPipe->In, &message, TRUE))
if (message.id == 0)
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
data = (wStream*) message.wParam;
if ((error = rdpsnd_recv_pdu(rdpsnd, data)))
{
data = (wStream*) message.wParam;
if (rdpsnd_recv_pdu(rdpsnd, data) != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "error treating sound channel message");
break;
}
WLog_ERR(TAG, "error treating sound channel message");
break;
}
}
}
out:
if (error && rdpsnd->rdpcontext)
setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_virtual_channel_client_thread reported an error");
rdpsnd_process_disconnect(rdpsnd);
ExitThread(0);
ExitThread((DWORD)error);
return NULL;
}
static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID pData, UINT32 dataLength)
static WIN32ERROR rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID pData, UINT32 dataLength)
{
UINT32 status;
status = plugin->channelEntryPoints.pVirtualChannelOpen(plugin->InitHandle,
&plugin->OpenHandle, plugin->channelDef.name, rdpsnd_virtual_channel_open_event);
if (!rdpsnd_add_open_handle_data(plugin->OpenHandle, plugin))
{
WLog_ERR(TAG, "%s: unable to register opened handle", __FUNCTION__);
return;
}
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
return status;
}
if (!rdpsnd_add_open_handle_data(plugin->OpenHandle, plugin))
{
WLog_ERR(TAG, "unable to register opened handle");
return ERROR_INTERNAL_ERROR;
}
plugin->MsgPipe = MessagePipe_New();
if (!plugin->MsgPipe)
{
WLog_ERR(TAG, "%s: unable to create message pipe", __FUNCTION__);
return;
WLog_ERR(TAG, "unable to create message pipe");
return CHANNEL_RC_NO_MEMORY;
}
plugin->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin, 0, NULL);
if (!plugin->thread)
{
WLog_ERR(TAG, "%s: unable to create thread", __FUNCTION__);
return;
WLog_ERR(TAG, "unable to create thread");
MessagePipe_Free(plugin->MsgPipe);
plugin->MsgPipe = NULL;
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
static void rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd)
static WIN32ERROR rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd)
{
UINT rc;
WIN32ERROR error;
MessagePipe_PostQuit(rdpsnd->MsgPipe, 0);
WaitForSingleObject(rdpsnd->thread, INFINITE);
@ -1176,11 +1274,12 @@ static void rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd)
CloseHandle(rdpsnd->thread);
rdpsnd->thread = NULL;
rc = rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);
if (CHANNEL_RC_OK != rc)
error = rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);
if (CHANNEL_RC_OK != error)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(rc), rc);
WTSErrorToString(error), error);
return error;
}
if (rdpsnd->data_in)
@ -1219,6 +1318,8 @@ static void rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd)
}
rdpsnd_remove_open_handle_data(rdpsnd->OpenHandle);
return CHANNEL_RC_OK;
}
static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
@ -1231,6 +1332,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
rdpsndPlugin* plugin;
WIN32ERROR error = CHANNEL_RC_OK;
plugin = (rdpsndPlugin*) rdpsnd_get_init_handle_data(pInitHandle);
@ -1243,17 +1345,21 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength);
if ((error = rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength)))
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_connected failed with error %lu!", error);
break;
case CHANNEL_EVENT_DISCONNECTED:
rdpsnd_virtual_channel_event_disconnected(plugin);
if ((error = rdpsnd_virtual_channel_event_disconnected(plugin)))
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_disconnected failed with error %lu!", error);
break;
case CHANNEL_EVENT_TERMINATED:
rdpsnd_virtual_channel_event_terminated(plugin);
break;
}
if (error && plugin->rdpcontext)
setChannelError(plugin->rdpcontext, error, "rdpsnd_virtual_channel_init_event reported an error");
}
/* rdpsnd is always built-in */
@ -1264,10 +1370,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
UINT rc;
rdpsndPlugin* rdpsnd;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
rdpsnd = (rdpsndPlugin*) calloc(1, sizeof(rdpsndPlugin));
if (!rdpsnd)
{
WLog_ERR(TAG, "calloc failed!");
return FALSE;
}
#if !defined(_WIN32) && !defined(ANDROID)
{
@ -1284,6 +1395,14 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
strcpy(rdpsnd->channelDef.name, "rdpsnd");
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
rdpsnd->rdpcontext = pEntryPointsEx->context;
}
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");

View File

@ -4,6 +4,8 @@
*
* Copyright 2009-2012 Jay Sorg
* Copyright 2010-2012 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -31,10 +33,12 @@
#include <winpr/crt.h>
#include <winpr/cmdline.h>
#include <winpr/win32error.h>
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/channels/log.h>
#include <winpr/win32error.h>
#include "rdpsnd_main.h"
@ -335,7 +339,7 @@ static void rdpsnd_winmm_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV
#define freerdp_rdpsnd_client_subsystem_entry winmm_freerdp_rdpsnd_client_subsystem_entry
#endif
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
WIN32ERROR freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
{
ADDIN_ARGV* args;
rdpsndWinmmPlugin* winmm;
@ -343,7 +347,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
winmm = (rdpsndWinmmPlugin*) calloc(1, sizeof(rdpsndWinmmPlugin));
if (!winmm)
return -1;
return CHANNEL_RC_NO_MEMORY;
winmm->device.DisableConfirmThread = TRUE;
@ -362,8 +366,13 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
rdpsnd_winmm_parse_addin_args((rdpsndDevicePlugin*) winmm, args);
winmm->dsp_context = freerdp_dsp_context_new();
if (!winmm->dsp_context)
{
free(winmm);
return CHANNEL_RC_NO_MEMORY;
}
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) winmm);
return 0;
return CHANNEL_RC_OK;
}

View File

@ -3,6 +3,8 @@
* Server Audio Virtual Channel
*
* Copyright 2012 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -33,7 +35,7 @@
#include "rdpsnd_main.h"
BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
WIN32ERROR rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
{
int pos;
UINT16 i;
@ -80,48 +82,61 @@ BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;
return status ? CHANNEL_RC_OK: ERROR_INTERNAL_ERROR;
}
static BOOL rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s)
static WIN32ERROR rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s)
{
UINT16 timestamp;
BYTE confirmBlockNum;
WIN32ERROR error = CHANNEL_RC_OK;
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
{
WLog_ERR(TAG, "not enought data in stream!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT16(s, timestamp);
Stream_Read_UINT8(s, confirmBlockNum);
Stream_Seek_UINT8(s);
IFCALL(context->ConfirmBlock, context, confirmBlockNum, timestamp);
IFCALLRET(context->ConfirmBlock, error, context, confirmBlockNum, timestamp);
if (error)
WLog_ERR(TAG, "context->ConfirmBlock failed with error %lu", error);
return TRUE;
return error;
}
static BOOL rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s)
static WIN32ERROR rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s)
{
UINT16 quality;
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
{
WLog_ERR(TAG, "not enought data in stream!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT16(s, quality);
Stream_Seek_UINT16(s); // reserved
WLog_ERR(TAG, "Client requested sound quality: %#0X", quality);
return TRUE;
WLog_DBG(TAG, "Client requested sound quality: %#0X", quality);
return CHANNEL_RC_OK;
}
static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
static WIN32ERROR rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
{
int i, num_known_format = 0;
UINT32 flags, vol, pitch;
UINT16 udpPort;
BYTE lastblock;
WIN32ERROR error = CHANNEL_RC_OK;
if (Stream_GetRemainingLength(s) < 20)
return FALSE;
{
WLog_ERR(TAG, "not enought data in stream!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, flags); /* dwFlags */
Stream_Read_UINT32(s, vol); /* dwVolume */
@ -134,22 +149,33 @@ static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
/* this check is only a guess as cbSize can influence the size of a format record */
if (Stream_GetRemainingLength(s) < context->num_client_formats * 18)
return FALSE;
{
WLog_ERR(TAG, "not enought data in stream!");
return ERROR_INVALID_DATA;
}
if (!context->num_client_formats)
{
WLog_ERR(TAG, "client doesn't support any format!");
return FALSE;
return ERROR_INTERNAL_ERROR;
}
context->client_formats = (AUDIO_FORMAT *)calloc(context->num_client_formats, sizeof(AUDIO_FORMAT));
if (!context->client_formats)
return FALSE;
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
for (i = 0; i < context->num_client_formats; i++)
{
if (Stream_GetRemainingLength(s) < 18)
{
WLog_ERR(TAG, "not enought data in stream!");
error = ERROR_INVALID_DATA;
goto out_free;
}
Stream_Read_UINT16(s, context->client_formats[i].wFormatTag);
Stream_Read_UINT16(s, context->client_formats[i].nChannels);
@ -162,7 +188,12 @@ static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
if (context->client_formats[i].cbSize > 0)
{
if (!Stream_SafeSeek(s, context->client_formats[i].cbSize))
{
WLog_ERR(TAG, "Stream_SafeSeek failed!");
error = ERROR_INTERNAL_ERROR;
goto out_free;
}
}
if (context->client_formats[i].wFormatTag != 0)
@ -179,11 +210,11 @@ static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
goto out_free;
}
return TRUE;
return CHANNEL_RC_OK;
out_free:
free(context->client_formats);
return FALSE;
return error;
}
static void* rdpsnd_server_thread(void* arg)
@ -191,39 +222,47 @@ static void* rdpsnd_server_thread(void* arg)
DWORD nCount, status;
HANDLE events[8];
RdpsndServerContext* context;
BOOL doRun;
WIN32ERROR error = CHANNEL_RC_OK;
context = (RdpsndServerContext *)arg;
nCount = 0;
events[nCount++] = context->priv->channelEvent;
events[nCount++] = context->priv->StopEvent;
if (!rdpsnd_server_send_formats(context, context->priv->rdpsnd_pdu))
if ((error = rdpsnd_server_send_formats(context, context->priv->rdpsnd_pdu)))
{
WLog_ERR(TAG, "rdpsnd_server_send_formats failed with error %lu", error);
goto out;
}
doRun = TRUE;
while (doRun)
while (TRUE)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
break;
if (rdpsnd_server_handle_messages(context) == 0)
if ((error = rdpsnd_server_handle_messages(context)))
{
WLog_ERR(TAG, "rdpsnd_server_handle_messages failed with error %lu", error);
break;
}
}
out:
if (error && context->rdpcontext)
setChannelError(context->rdpcontext, error, "rdpsnd_server_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}
static BOOL rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread)
static WIN32ERROR rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread)
{
context->priv->ownThread = ownThread;
return context->Start(context) >= 0;
return context->Start(context);
}
static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index)
static WIN32ERROR rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index)
{
int bs;
int out_buffer_size;
@ -232,7 +271,7 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client
if (client_format_index < 0 || client_format_index >= context->num_client_formats)
{
WLog_ERR(TAG, "index %d is not correct.", client_format_index);
return FALSE;
return ERROR_INVALID_DATA;
}
context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8;
@ -244,7 +283,7 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client
if (format->nSamplesPerSec == 0)
{
WLog_ERR(TAG, "invalid Client Sound Format!!");
return FALSE;
return ERROR_INVALID_DATA;
}
switch(format->wFormatTag)
@ -277,17 +316,20 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client
newBuffer = (BYTE *)realloc(context->priv->out_buffer, out_buffer_size);
if (!newBuffer)
return FALSE;
{
WLog_ERR(TAG, "realloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
context->priv->out_buffer = newBuffer;
context->priv->out_buffer_size = out_buffer_size;
}
freerdp_dsp_context_reset_adpcm(context->priv->dsp_context);
return TRUE;
return CHANNEL_RC_OK;
}
static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
static WIN32ERROR rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
{
int size;
BYTE* src;
@ -298,6 +340,7 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
int tbytes_per_frame;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
WIN32ERROR error = CHANNEL_RC_OK;
format = &context->client_formats[context->selected_client_format];
tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample;
@ -360,13 +403,19 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
if (!status)
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
error = ERROR_INTERNAL_ERROR;
goto out;
}
Stream_SetPosition(s, 0);
/* Wave PDU */
if (!Stream_EnsureRemainingCapacity(s, size + fill_size))
{
status = -1;
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
error = CHANNEL_RC_NO_MEMORY;
goto out;
}
Stream_Write_UINT32(s, 0); /* bPad */
@ -377,19 +426,26 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
if (!status)
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
error = ERROR_INTERNAL_ERROR;
}
out:
Stream_SetPosition(s, 0);
context->priv->out_pending_frames = 0;
return status;
return error;
}
static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp)
static WIN32ERROR rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp)
{
int cframes;
int cframesize;
WIN32ERROR error = CHANNEL_RC_OK;
if (context->selected_client_format < 0)
return FALSE;
return ERROR_INVALID_DATA;
while (nframes > 0)
{
@ -404,15 +460,16 @@ static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void*
if (context->priv->out_pending_frames >= context->priv->out_frames)
{
if (!rdpsnd_server_send_audio_pdu(context, wTimestamp))
return FALSE;
if ((error = rdpsnd_server_send_audio_pdu(context, wTimestamp)))
WLog_ERR(TAG, "rdpsnd_server_send_audio_pdu failed with error %lu", error);
}
}
return TRUE;
return error;
}
static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right)
static WIN32ERROR rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right)
{
int pos;
BOOL status;
@ -433,23 +490,27 @@ static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
}
static BOOL rdpsnd_server_close(RdpsndServerContext* context)
static WIN32ERROR rdpsnd_server_close(RdpsndServerContext* context)
{
int pos;
BOOL status;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
WIN32ERROR error = CHANNEL_RC_OK;
if (context->selected_client_format < 0)
return FALSE;
return ERROR_INVALID_DATA;
if (context->priv->out_pending_frames > 0)
{
if (!rdpsnd_server_send_audio_pdu(context, 0))
return FALSE;
if ((error = rdpsnd_server_send_audio_pdu(context, 0)))
{
WLog_ERR(TAG, "rdpsnd_server_send_audio_pdu failed with error %lu", error);
return error;
}
}
context->selected_client_format = -1;
@ -465,18 +526,22 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context)
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
}
static int rdpsnd_server_start(RdpsndServerContext* context)
static WIN32ERROR rdpsnd_server_start(RdpsndServerContext* context)
{
void *buffer = NULL;
DWORD bytesReturned;
RdpsndServerPrivate *priv = context->priv;
WIN32ERROR error = ERROR_INTERNAL_ERROR;
priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd");
if (!priv->ChannelHandle)
return -1;
{
WLog_ERR(TAG, "WTSVirtualChannelOpen failed!");
return ERROR_INTERNAL_ERROR;
}
if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE)))
{
@ -492,22 +557,32 @@ static int rdpsnd_server_start(RdpsndServerContext* context)
priv->rdpsnd_pdu = Stream_New(NULL, 4096);
if (!priv->rdpsnd_pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
error = CHANNEL_RC_NO_MEMORY;
goto out_close;
}
if (priv->ownThread)
{
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!context->priv->StopEvent)
{
WLog_ERR(TAG, "CreateEvent failed!");
goto out_pdu;
}
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
if (!context->priv->Thread)
{
WLog_ERR(TAG, "CreateThread failed!");
goto out_stopEvent;
}
}
return 0;
return CHANNEL_RC_OK;
out_stopEvent:
CloseHandle(context->priv->StopEvent);
@ -518,10 +593,10 @@ out_pdu:
out_close:
WTSVirtualChannelClose(context->priv->ChannelHandle);
context->priv->ChannelHandle = NULL;
return -1;
return error;
}
static int rdpsnd_server_stop(RdpsndServerContext* context)
static WIN32ERROR rdpsnd_server_stop(RdpsndServerContext* context)
{
if (context->priv->ownThread)
{
@ -538,7 +613,7 @@ static int rdpsnd_server_stop(RdpsndServerContext* context)
if (context->priv->rdpsnd_pdu)
Stream_Free(context->priv->rdpsnd_pdu, TRUE);
return 0;
return CHANNEL_RC_OK;
}
RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
@ -548,7 +623,10 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
context = (RdpsndServerContext *)calloc(1, sizeof(RdpsndServerContext));
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
return NULL;
}
context->vcm = vcm;
@ -564,15 +642,24 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
context->priv = priv = (RdpsndServerPrivate *)calloc(1, sizeof(RdpsndServerPrivate));
if (!priv)
{
WLog_ERR(TAG, "calloc failed!");
goto out_free;
}
priv->dsp_context = freerdp_dsp_context_new();
if (!priv->dsp_context)
{
WLog_ERR(TAG, "freerdp_dsp_context_new failed!");
goto out_free_priv;
}
priv->input_stream = Stream_New(NULL, 4);
if (!priv->input_stream)
{
WLog_ERR(TAG, "Stream_New failed!");
goto out_free_dsp;
}
priv->expectedBytes = 4;
priv->waitingHeader = TRUE;
@ -625,14 +712,13 @@ HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context)
*
* @param Server side context
*
* @return -1 if no data could be read,
* 0 on error (like connection close),
* 1 on succsess (also if further bytes need to be read)
* @return 0 on success
* otherwise error
*/
int rdpsnd_server_handle_messages(RdpsndServerContext *context)
WIN32ERROR rdpsnd_server_handle_messages(RdpsndServerContext *context)
{
DWORD bytesReturned;
BOOL ret;
WIN32ERROR ret = CHANNEL_RC_OK;
RdpsndServerPrivate *priv = context->priv;
wStream *s = priv->input_stream;
@ -640,16 +726,16 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context)
if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
{
if (GetLastError() == ERROR_NO_DATA)
return -1;
return CHANNEL_RC_OK;
WLog_ERR(TAG, "channel connection closed");
return 0;
return ERROR_INTERNAL_ERROR;
}
priv->expectedBytes -= bytesReturned;
Stream_Seek(s, bytesReturned);
if (priv->expectedBytes)
return 1;
return CHANNEL_RC_OK;
Stream_SealLength(s);
Stream_SetPosition(s, 0);
@ -665,8 +751,11 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context)
if (priv->expectedBytes)
{
if (!Stream_EnsureCapacity(s, priv->expectedBytes))
return 0;
return 1;
{
WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
return CHANNEL_RC_OK;
}
}
@ -686,7 +775,7 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context)
case SNDC_FORMATS:
ret = rdpsnd_server_recv_formats(context, s);
if (ret && context->clientVersion < 6)
if ((ret == CHANNEL_RC_OK) && (context->clientVersion < 6))
IFCALL(context->Activated, context);
break;
@ -695,19 +784,16 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context)
ret = rdpsnd_server_recv_quality_mode(context, s);
Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */
if (ret && context->clientVersion >= 6)
if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= 6))
IFCALL(context->Activated, context);
break;
default:
WLog_ERR(TAG, "UNKOWN MESSAGE TYPE!! (%#0X)", priv->msgType);
ret = FALSE;
ret = ERROR_INVALID_DATA;
break;
}
Stream_SetPosition(s, 0);
if (ret)
return 1;
else
return 0;
return ret;
}

View File

@ -589,7 +589,7 @@ static WIN32ERROR remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDE
static WIN32ERROR remdesk_process_receive(remdeskPlugin* remdesk, wStream* s)
{
WIN32ERROR status = CHANNEL_RC_OK;
WIN32ERROR status;
REMDESK_CHANNEL_HEADER header;
#if 0
@ -775,7 +775,11 @@ static WIN32ERROR remdesk_virtual_channel_event_data_received(remdeskPlugin* rem
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(remdesk->queue, NULL, 0, (void*) data_in, NULL);
if (!MessageQueue_Post(remdesk->queue, NULL, 0, (void*) data_in, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
}
return CHANNEL_RC_OK;
}
@ -784,23 +788,21 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
remdeskPlugin* remdesk;
WIN32ERROR error;
remdesk = (remdeskPlugin*) remdesk_get_open_handle_data(openHandle);
if (!remdesk)
{
WLog_ERR(TAG, "error no match");
remdesk->error = CHANNEL_RC_BAD_CHANNEL;
//TODO report error
return;
}
remdesk->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
if ((remdesk->error = remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags)))
WLog_ERR(TAG, "remdesk_virtual_channel_event_data_received failed with error %lu!", remdesk->error);
if ((error = remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags)))
WLog_ERR(TAG, "remdesk_virtual_channel_event_data_received failed with error %lu!", error);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
@ -810,7 +812,9 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT
case CHANNEL_EVENT_USER:
break;
}
//TODO report error
if (error && remdesk->rdpcontext)
setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_open_event reported an error");
}
static void* remdesk_virtual_channel_client_thread(void* arg)
@ -825,25 +829,34 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(remdesk->queue))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (!MessageQueue_Peek(remdesk->queue, &message, TRUE)) {
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
if (MessageQueue_Peek(remdesk->queue, &message, TRUE))
if (message.id == 0)
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
data = (wStream*) message.wParam;
if ((error = remdesk_process_receive(remdesk, data)))
{
data = (wStream*) message.wParam;
if ((error = remdesk_process_receive(remdesk, data)))
{
WLog_ERR(TAG, "remdesk_process_receive failed with error %lu!", error);
break;
}
WLog_ERR(TAG, "remdesk_process_receive failed with error %lu!", error);
break;
}
}
}
if (error && remdesk->rdpcontext)
setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -933,36 +946,34 @@ static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
remdeskPlugin* remdesk;
WIN32ERROR error = CHANNEL_RC_OK;
remdesk = (remdeskPlugin*) remdesk_get_init_handle_data(pInitHandle);
if (!remdesk)
{
WLog_ERR(TAG, "error no match");
remdesk->error = CHANNEL_RC_BAD_CHANNEL;
//TODO report error
return;
}
remdesk->error = CHANNEL_RC_OK;
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
if ((remdesk->error = remdesk_virtual_channel_event_connected(remdesk, pData, dataLength)))
WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu", remdesk->error);
if ((error = remdesk_virtual_channel_event_connected(remdesk, pData, dataLength)))
WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu", error);
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((remdesk->error = remdesk_virtual_channel_event_disconnected(remdesk)))
WLog_ERR(TAG, "remdesk_virtual_channel_event_disconnected failed with error %lu", remdesk->error);
if ((error = remdesk_virtual_channel_event_disconnected(remdesk)))
WLog_ERR(TAG, "remdesk_virtual_channel_event_disconnected failed with error %lu", error);
break;
case CHANNEL_EVENT_TERMINATED:
remdesk_virtual_channel_event_terminated(remdesk);
break;
}
//TODO report error
if (error && remdesk->rdpcontext)
setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_init_event reported an error");
}
/* remdesk is always built-in */
@ -1011,6 +1022,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
*(pEntryPointsEx->ppInterface) = (void*) context;
remdesk->context = context;
remdesk->rdpcontext = pEntryPointsEx->context;
}
CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));

View File

@ -56,7 +56,7 @@ struct remdesk_plugin
char* ExpertBlob;
BYTE* EncryptedPassStub;
int EncryptedPassStubSize;
WIN32ERROR error;
rdpContext* rdpcontext;
};
typedef struct remdesk_plugin remdeskPlugin;

View File

@ -543,8 +543,8 @@ static void* remdesk_server_thread(void* arg)
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
ExitThread(CHANNEL_RC_NO_MEMORY);
return NULL;
error = CHANNEL_RC_NO_MEMORY;
goto out;
}
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
@ -557,8 +557,8 @@ static void* remdesk_server_thread(void* arg)
else
{
WLog_ERR(TAG, "WTSVirtualChannelQuery failed!");
ExitThread(ERROR_INTERNAL_ERROR);
return NULL;
error = ERROR_INTERNAL_ERROR;
goto out;
}
nCount = 0;
@ -568,8 +568,7 @@ static void* remdesk_server_thread(void* arg)
if ((error = remdesk_send_ctl_version_info_pdu(context)))
{
WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
goto out;
}
while (1)
@ -617,7 +616,10 @@ static void* remdesk_server_thread(void* arg)
}
Stream_Free(s, TRUE);
//TODO signal error
out:
if (error && context->rdpcontext)
setChannelError(context->rdpcontext, error, "remdesk_server_thread reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -638,7 +640,6 @@ static WIN32ERROR remdesk_server_start(RemdeskServerContext* context)
return ERROR_INTERNAL_ERROR;
}
//TODO implement error reporting
if (!(context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL)))
{

View File

@ -68,6 +68,7 @@ struct _SERIAL_DEVICE
wListDictionary *IrpThreads;
UINT32 IrpThreadToBeTerminatedCount;
CRITICAL_SECTION TerminatingIrpThreadsLock;
rdpContext* rdpcontext;
};
typedef struct _IRP_THREAD_DATA IRP_THREAD_DATA;
@ -454,22 +455,29 @@ static void* irp_thread_func(void* arg)
/* blocks until the end of the request */
if ((error = serial_process_irp(data->serial, data->irp)))
{
WLog_ERR(TAG, "serial_process_irp failed with error %lu", error);
goto error_out;
}
EnterCriticalSection(&data->serial->TerminatingIrpThreadsLock);
data->serial->IrpThreadToBeTerminatedCount++;
data->irp->Complete(data->irp);
error = data->irp->Complete(data->irp);
LeaveCriticalSection(&data->serial->TerminatingIrpThreadsLock);
error_out:
if (error && data->serial->rdpcontext)
setChannelError(data->serial->rdpcontext, error, "irp_thread_func reported an error");
/* NB: At this point, the server might already being reusing
* the CompletionId whereas the thread is not yet
* terminated */
free(data);
ExitThread(0);
ExitThread((DWORD)error);
return NULL;
}
@ -477,7 +485,7 @@ static void* irp_thread_func(void* arg)
static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
{
IRP_THREAD_DATA *data = NULL;
HANDLE irpThread = INVALID_HANDLE_VALUE;
HANDLE irpThread;
HANDLE previousIrpThread;
uintptr_t key;
@ -630,7 +638,11 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
key = irp->CompletionId;
ListDictionary_Add(serial->IrpThreads, (void*)key, irpThread);
if (!ListDictionary_Add(serial->IrpThreads, (void*)key, irpThread))
{
WLog_ERR(TAG, "ListDictionary_Add failed!");
goto error_handle;
}
return;
@ -677,14 +689,23 @@ static void* serial_thread_func(void* arg)
IRP* irp;
wMessage message;
SERIAL_DEVICE* serial = (SERIAL_DEVICE*) arg;
WIN32ERROR error = CHANNEL_RC_OK;
while (1)
{
if (!MessageQueue_Wait(serial->MainIrpQueue))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (!MessageQueue_Peek(serial->MainIrpQueue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
{
@ -698,7 +719,10 @@ static void* serial_thread_func(void* arg)
create_irp_thread(serial, irp);
}
ExitThread(0);
if (error && serial->rdpcontext)
setChannelError(serial->rdpcontext, error, "serial_thread_func reported an error");
ExitThread((DWORD) error);
return NULL;
}
@ -717,7 +741,11 @@ static WIN32ERROR serial_irp_request(DEVICE* device, IRP* irp)
* write requests.
*/
MessageQueue_Post(serial->MainIrpQueue, NULL, 0, (void*) irp, NULL);
if (!MessageQueue_Post(serial->MainIrpQueue, NULL, 0, (void*) irp, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
@ -809,6 +837,7 @@ WIN32ERROR DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
serial->device.name = name;
serial->device.IRPRequest = serial_irp_request;
serial->device.Free = serial_free;
serial->rdpcontext = pEntryPoints->rdpcontext;
len = strlen(name);
serial->device.data = Stream_New(NULL, len + 1);

View File

@ -41,6 +41,7 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
wMessage message;
SMARTCARD_DEVICE* smartcard;
SMARTCARD_OPERATION* operation;
WIN32ERROR error = CHANNEL_RC_OK;
smartcard = pContext->smartcard;
@ -54,7 +55,12 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
if (WaitForSingleObject(MessageQueue_Event(pContext->IrpQueue), 0) == WAIT_OBJECT_0)
{
if (!MessageQueue_Peek(pContext->IrpQueue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
status = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
break;
@ -69,14 +75,23 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
break;
}
Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) operation->irp);
if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) operation->irp))
{
WLog_ERR(TAG, "Queue_Enqueue failed!");
status = ERROR_INTERNAL_ERROR;
break;
}
free(operation);
}
}
}
ExitThread(0);
if (status && smartcard->rdpcontext)
setChannelError(smartcard->rdpcontext, error, "smartcard_context_thread reported an error");
ExitThread((DWORD)status);
return NULL;
}
@ -86,20 +101,30 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTE
pContext = (SMARTCARD_CONTEXT*) calloc(1, sizeof(SMARTCARD_CONTEXT));
if (!pContext)
{
WLog_ERR(TAG, "calloc failed!");
return pContext;
}
pContext->smartcard = smartcard;
pContext->hContext = hContext;
pContext->IrpQueue = MessageQueue_New(NULL);
if (!pContext->IrpQueue)
{
WLog_ERR(TAG, "MessageQueue_New failed!");
goto error_irpqueue;
}
pContext->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) smartcard_context_thread,
pContext, 0, NULL);
if (!pContext->thread)
{
WLog_ERR(TAG, "CreateThread failed!");
goto error_thread;
}
return pContext;
error_thread:
@ -248,29 +273,6 @@ WIN32ERROR smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
return irp->Complete(irp);
}
void* smartcard_process_irp_worker_proc(SMARTCARD_OPERATION* operation)
{
IRP* irp;
LONG status;
SMARTCARD_DEVICE* smartcard;
irp = operation->irp;
smartcard = (SMARTCARD_DEVICE*) irp->device;
if ((status = smartcard_irp_device_control_call(smartcard, operation)))
{
WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu", status);
//TODO report error
}
Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp);
free(operation);
ExitThread(0);
return NULL;
}
/**
* Multiple threads and SCardGetStatusChange:
* http://musclecard.996296.n3.nabble.com/Multiple-threads-and-SCardGetStatusChange-td4430.html
@ -456,7 +458,12 @@ static void* smartcard_thread_func(void* arg)
if (WaitForSingleObject(MessageQueue_Event(smartcard->IrpQueue), 0) == WAIT_OBJECT_0)
{
if (!MessageQueue_Peek(smartcard->IrpQueue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (message.id == WMQ_QUIT)
{
@ -518,7 +525,9 @@ static void* smartcard_thread_func(void* arg)
}
}
out:
//TODO signal error
if (error && smartcard->rdpcontext)
setChannelError(smartcard->rdpcontext, error, "smartcard_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
}
@ -526,7 +535,11 @@ out:
static WIN32ERROR smartcard_irp_request(DEVICE* device, IRP* irp)
{
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
MessageQueue_Post(smartcard->IrpQueue, NULL, 0, (void*) irp, NULL);
if (!MessageQueue_Post(smartcard->IrpQueue, NULL, 0, (void*) irp, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
@ -560,6 +573,7 @@ WIN32ERROR DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
smartcard->device.IRPRequest = smartcard_irp_request;
smartcard->device.Init = smartcard_init;
smartcard->device.Free = smartcard_free;
smartcard->rdpcontext = pEntryPoints->rdpcontext;
length = strlen(smartcard->device.name);
smartcard->device.data = Stream_New(NULL, length + 1);

View File

@ -119,6 +119,7 @@ struct _SMARTCARD_DEVICE
wQueue* CompletedIrpQueue;
wListDictionary* rgSCardContextList;
wListDictionary* rgOutstandingMessages;
rdpContext* rdpcontext;
};
SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTEXT hContext);

View File

@ -4,6 +4,8 @@
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -180,7 +182,7 @@ WIN32ERROR tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
return status;
}
WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman, rdpContext* rdpcontext)
{
UINT32 StreamId;
WIN32ERROR status = CHANNEL_RC_OK;
@ -203,7 +205,7 @@ WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
{
Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numMediaType */
stream = tsmf_stream_new(presentation, StreamId);
stream = tsmf_stream_new(presentation, StreamId, rdpcontext);
if (!stream)
return ERROR_OUTOFMEMORY;

View File

@ -3,6 +3,8 @@
* Video Redirection Virtual Channel - Interface Manipulation
*
* Copyright 2010-2011 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,6 +22,8 @@
#ifndef __TSMF_IFMAN_H
#define __TSMF_IFMAN_H
#include <freerdp/freerdp.h>
typedef struct _TSMF_IFMAN TSMF_IFMAN;
struct _TSMF_IFMAN
{
@ -42,7 +46,7 @@ WIN32ERROR tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman);
WIN32ERROR tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman);
WIN32ERROR tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman);
WIN32ERROR tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman);
WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman);
WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman, rdpContext* rdpcontext);
WIN32ERROR tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman);
WIN32ERROR tsmf_ifman_remove_stream(TSMF_IFMAN* ifman);
WIN32ERROR tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman);

View File

@ -3,6 +3,8 @@
* Video Redirection Virtual Channel
*
* Copyright 2010-2011 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -170,7 +172,7 @@ static WIN32ERROR tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCall
processed = TRUE;
break;
case ADD_STREAM:
error = tsmf_ifman_add_stream(&ifman);
error = tsmf_ifman_add_stream(&ifman, ((TSMF_PLUGIN*) callback->plugin)->rdpcontext);
processed = TRUE;
break;
case SET_TOPOLOGY_REQ:
@ -461,7 +463,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
WIN32ERROR status = 0;
TSMF_PLUGIN* tsmf;
TsmfClientContext* context;
WIN32ERROR error = ERROR_OUTOFMEMORY;
WIN32ERROR error = CHANNEL_RC_NO_MEMORY;
tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
@ -469,16 +471,25 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
tsmf = (TSMF_PLUGIN*) calloc(1, sizeof(TSMF_PLUGIN));
if (!tsmf)
return ERROR_OUTOFMEMORY;
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
tsmf->iface.Initialize = tsmf_plugin_initialize;
tsmf->iface.Connected = NULL;
tsmf->iface.Disconnected = NULL;
tsmf->iface.Terminated = tsmf_plugin_terminated;
tsmf->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context;
context = (TsmfClientContext*) calloc(1, sizeof(TsmfClientContext));
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
goto error_context;
}
context->handle = (void*) tsmf;
tsmf->iface.pInterface = (void*) context;
@ -492,7 +503,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
}
if (status == 0)
if (status == CHANNEL_RC_OK)
{
status = tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
}

View File

@ -3,6 +3,8 @@
* Video Redirection Virtual Channel
*
* Copyright 2010-2011 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,6 +22,8 @@
#ifndef __TSMF_MAIN_H
#define __TSMF_MAIN_H
#include <freerdp/freerdp.h>
typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK;
typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK;
@ -56,6 +60,8 @@ struct _TSMF_PLUGIN
const char* decoder_name;
const char* audio_name;
const char* audio_device;
rdpContext* rdpcontext;
};
BOOL tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,

View File

@ -4,6 +4,8 @@
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -110,6 +112,7 @@ struct _TSMF_STREAM
wQueue *sample_list;
wQueue *sample_ack_list;
rdpContext* rdpcontext;
};
struct _TSMF_SAMPLE
@ -596,6 +599,7 @@ static void* tsmf_stream_ack_func(void *arg)
{
HANDLE hdl[2];
TSMF_STREAM* stream = (TSMF_STREAM*) arg;
WIN32ERROR error = CHANNEL_RC_OK;
DEBUG_TSMF("in %d", stream->stream_id);
hdl[0] = stream->stopEvent;
@ -615,9 +619,17 @@ static void* tsmf_stream_ack_func(void *arg)
continue;
if (tsmf_stream_process_ack(stream, FALSE))
{
error = ERROR_INTERNAL_ERROR;
WLog_ERR(TAG, "tsmf_stream_process_ack failed!");
break;
}
}
if (error && stream->rdpcontext)
setChannelError(stream->rdpcontext, error, "tsmf_stream_ack_func reported an error");
DEBUG_TSMF("out %d", stream->stream_id);
ExitThread(0);
return NULL;
@ -629,6 +641,7 @@ static void* tsmf_stream_playback_func(void *arg)
TSMF_SAMPLE* sample;
TSMF_STREAM* stream = (TSMF_STREAM *) arg;
TSMF_PRESENTATION* presentation = stream->presentation;
WIN32ERROR error = CHANNEL_RC_OK;
DEBUG_TSMF("in %d", stream->stream_id);
@ -661,6 +674,7 @@ static void* tsmf_stream_playback_func(void *arg)
if (sample && !tsmf_sample_playback(sample))
{
WLog_ERR(TAG, "error playing sample");
error = ERROR_INTERNAL_ERROR;
break;
}
}
@ -671,6 +685,9 @@ static void* tsmf_stream_playback_func(void *arg)
stream->audio = NULL;
}
if (error && stream->rdpcontext)
setChannelError(stream->rdpcontext, error, "tsmf_stream_playback_func reported an error");
DEBUG_TSMF("out %d", stream->stream_id);
ExitThread(0);
return NULL;
@ -972,7 +989,7 @@ void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
ArrayList_Remove(presentation_list, presentation);
}
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id, rdpContext* rdpcontext)
{
TSMF_STREAM* stream;
stream = tsmf_stream_find_by_id(presentation, stream_id);
@ -1017,6 +1034,8 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
if (ArrayList_Add(presentation->stream_list, stream) < 0)
goto error_add;
stream->rdpcontext = rdpcontext;
return stream;
error_add:

View File

@ -4,6 +4,8 @@
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,6 +28,8 @@
#ifndef __TSMF_MEDIA_H
#define __TSMF_MEDIA_H
#include <freerdp/freerdp.h>
typedef struct _TSMF_PRESENTATION TSMF_PRESENTATION;
typedef struct _TSMF_STREAM TSMF_STREAM;
@ -48,7 +52,7 @@ void tsmf_presentation_set_audio_device(TSMF_PRESENTATION *presentation,
BOOL tsmf_presentation_flush(TSMF_PRESENTATION *presentation);
void tsmf_presentation_free(TSMF_PRESENTATION *presentation);
TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id);
TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id, rdpContext* rdpcontext);
TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stream_id);
BOOL tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s);
void tsmf_stream_end(TSMF_STREAM *stream);

View File

@ -373,10 +373,11 @@ struct _DEVICE_SERVICE_ENTRY_POINTS
pcRegisterDevice RegisterDevice;
RDPDR_DEVICE* device;
rdpContext* rdpcontext;
};
typedef struct _DEVICE_SERVICE_ENTRY_POINTS DEVICE_SERVICE_ENTRY_POINTS;
typedef DEVICE_SERVICE_ENTRY_POINTS* PDEVICE_SERVICE_ENTRY_POINTS;
typedef int (*PDEVICE_SERVICE_ENTRY)(PDEVICE_SERVICE_ENTRY_POINTS);
typedef WIN32ERROR (*PDEVICE_SERVICE_ENTRY)(PDEVICE_SERVICE_ENTRY_POINTS);
#endif /* FREERDP_CHANNEL_RDPDR_H */

View File

@ -23,6 +23,7 @@
#define FREERDP_CHANNEL_CLIENT_AUDIN_H
#include <freerdp/channels/audin.h>
#include <freerdp/freerdp.h>
/**
* Subsystem Interface
@ -61,6 +62,7 @@ struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS
IWTSPlugin* plugin;
PREGISTERAUDINDEVICE pRegisterAudinDevice;
ADDIN_ARGV* args;
rdpContext* rdpcontext;
};
typedef struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS FREERDP_AUDIN_DEVICE_ENTRY_POINTS;
typedef FREERDP_AUDIN_DEVICE_ENTRY_POINTS* PFREERDP_AUDIN_DEVICE_ENTRY_POINTS;

View File

@ -27,6 +27,7 @@
#include <freerdp/message.h>
#include <freerdp/channels/cliprdr.h>
#include <freerdp/freerdp.h>
/**
* Client Interface
@ -80,6 +81,8 @@ struct _cliprdr_client_context
pcCliprdrServerFileContentsRequest ServerFileContentsRequest;
pcCliprdrClientFileContentsResponse ClientFileContentsResponse;
pcCliprdrServerFileContentsResponse ServerFileContentsResponse;
rdpContext* rdpcontext;
};
struct _CLIPRDR_FORMAT_NAME

View File

@ -98,7 +98,7 @@ struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS
typedef struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS FREERDP_RDPSND_DEVICE_ENTRY_POINTS;
typedef FREERDP_RDPSND_DEVICE_ENTRY_POINTS* PFREERDP_RDPSND_DEVICE_ENTRY_POINTS;
typedef int (*PFREERDP_RDPSND_DEVICE_ENTRY)(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints);
typedef WIN32ERROR (*PFREERDP_RDPSND_DEVICE_ENTRY)(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints);
#endif /* FREERDP_CHANNEL_CLIENT_RDPSND_H */

View File

@ -3,8 +3,8 @@
* FreeRDP Interface
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -110,7 +110,11 @@ struct rdp_context
ALIGN64 wPubSub* pubSub; /* (offset 18) */
UINT64 paddingB[32 - 19]; /* 19 */
ALIGN64 HANDLE channelErrorEvent; /* (offset 19)*/
ALIGN64 WIN32ERROR channelErrorNum; /*(offset 20)*/
ALIGN64 char* errorDescription; /*(offset 21)*/
UINT64 paddingB[32 - 22]; /* 22 */
ALIGN64 rdpRdp* rdp; /**< (offset 32)
Pointer to a rdp_rdp structure used to keep the connection's parameters.
@ -280,6 +284,12 @@ FREERDP_API void freerdp_set_last_error(rdpContext* context, UINT32 lastError);
FREERDP_API ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount);
FREERDP_API HANDLE getChannelErrorEventHandle(rdpContext* context);
FREERDP_API WIN32ERROR getChannelError(rdpContext* context);
FREERDP_API const char* getChannelErrorDescription(rdpContext* context);
FREERDP_API void setChannelError(rdpContext* context, WIN32ERROR errorNum, char* description);
FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context);
#ifdef __cplusplus
}
#endif

View File

@ -91,6 +91,8 @@ struct _audin_server_context
* server must be careful of thread synchronization.
*/
psAudinServerReceiveSamples ReceiveSamples;
rdpContext* rdpcontext;
};
#ifdef __cplusplus

View File

@ -95,6 +95,8 @@ struct _cliprdr_server_context
psCliprdrServerFileContentsRequest ServerFileContentsRequest;
psCliprdrClientFileContentsResponse ClientFileContentsResponse;
psCliprdrServerFileContentsResponse ServerFileContentsResponse;
rdpContext* rdpcontext;
};
#ifdef __cplusplus

View File

@ -72,6 +72,8 @@ struct _echo_server_context
* Receive echo response PDU.
*/
psEchoServerResponse Response;
rdpContext* rdpcontext;
};
#ifdef __cplusplus

View File

@ -71,6 +71,8 @@ struct _encomsp_server_context
psEncomspGraphicsStreamResumed GraphicsStreamResumed;
EncomspServerPrivate* priv;
rdpContext* rdpcontext;
};
#ifdef __cplusplus

View File

@ -137,6 +137,8 @@ struct _rdpdr_server_context
/*** Smartcard callbacks registered by the server. ***/
psRdpdrOnSmartcardCreate OnSmartcardCreate;
psRdpdrOnSmartcardDelete OnSmartcardDelete;
rdpContext* rdpcontext;
};
#ifdef __cplusplus

View File

@ -3,6 +3,8 @@
* Server Audio Virtual Channel
*
* Copyright 2012 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,15 +29,15 @@ typedef struct _rdpsnd_server_context RdpsndServerContext;
typedef struct _rdpsnd_server_context rdpsnd_server_context;
typedef struct _rdpsnd_server_private RdpsndServerPrivate;
typedef int (*psRdpsndStart)(RdpsndServerContext* context);
typedef int (*psRdpsndStop)(RdpsndServerContext* context);
typedef WIN32ERROR (*psRdpsndStart)(RdpsndServerContext* context);
typedef WIN32ERROR (*psRdpsndStop)(RdpsndServerContext* context);
typedef BOOL (*psRdpsndServerInitialize)(RdpsndServerContext* context, BOOL ownThread);
typedef BOOL (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index);
typedef BOOL (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp);
typedef BOOL (*psRdpsndServerConfirmBlock)(RdpsndServerContext* context, BYTE confirmBlockNum, UINT16 wtimestamp);
typedef BOOL (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right);
typedef BOOL (*psRdpsndServerClose)(RdpsndServerContext* context);
typedef WIN32ERROR (*psRdpsndServerInitialize)(RdpsndServerContext* context, BOOL ownThread);
typedef WIN32ERROR (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index);
typedef WIN32ERROR (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp);
typedef WIN32ERROR (*psRdpsndServerConfirmBlock)(RdpsndServerContext* context, BYTE confirmBlockNum, UINT16 wtimestamp);
typedef WIN32ERROR (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right);
typedef WIN32ERROR (*psRdpsndServerClose)(RdpsndServerContext* context);
typedef void (*psRdpsndServerActivated)(RdpsndServerContext* context);
@ -110,6 +112,8 @@ struct _rdpsnd_server_context
* MS-RDPEA channel version the client announces
*/
UINT16 clientVersion;
rdpContext* rdpcontext;
};
#ifdef __cplusplus
@ -120,8 +124,8 @@ FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm);
FREERDP_API void rdpsnd_server_context_reset(RdpsndServerContext *);
FREERDP_API void rdpsnd_server_context_free(RdpsndServerContext* context);
FREERDP_API HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context);
FREERDP_API int rdpsnd_server_handle_messages(RdpsndServerContext *context);
FREERDP_API BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s);
FREERDP_API WIN32ERROR rdpsnd_server_handle_messages(RdpsndServerContext *context);
FREERDP_API WIN32ERROR rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s);
#ifdef __cplusplus

View File

@ -47,6 +47,7 @@ struct _remdesk_server_context
psRemdeskStop Stop;
RemdeskServerPrivate* priv;
rdpContext* rdpcontext;
};
#ifdef __cplusplus

View File

@ -3,6 +3,8 @@
* Static Virtual Channel Interface
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,6 +26,7 @@
#include <freerdp/types.h>
#include <winpr/wtsapi.h>
#include <freerdp/freerdp.h>
#define CHANNEL_EVENT_USER 1000
@ -45,6 +48,7 @@ struct _CHANNEL_ENTRY_POINTS_FREERDP
void* pExtendedData; /* extended initial data */
void* pInterface; /* channel callback interface, use after initialization */
void** ppInterface; /* channel callback interface, use for initialization */
rdpContext* context;
};
typedef struct _CHANNEL_ENTRY_POINTS_FREERDP CHANNEL_ENTRY_POINTS_FREERDP;
typedef CHANNEL_ENTRY_POINTS_FREERDP* PCHANNEL_ENTRY_POINTS_FREERDP;

View File

@ -3,6 +3,8 @@
* Client Channels
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -721,6 +723,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, P
EntryPoints.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER;
EntryPoints.ppInterface = &g_pInterface;
EntryPoints.pExtendedData = data;
EntryPoints.context = ((freerdp*)settings->instance)->context;
/* enable VirtualChannelInit */
channels->can_call_init = TRUE;

View File

@ -3,7 +3,8 @@
* FreeRDP Core
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -229,8 +230,11 @@ DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count
if (nCount == 0)
return 0;
if (events && (nCount < count))
if (events && (nCount < count + 1))
{
events[nCount++] = freerdp_channels_get_event_handle(context->instance);
events[nCount++] = getChannelErrorEventHandle(context);
}
else
return 0;
@ -248,6 +252,11 @@ BOOL freerdp_check_event_handles(rdpContext* context)
status = freerdp_channels_check_fds(context->channels, context->instance);
if (!status)
return FALSE;
status = checkChannelErrorEvent(context);
return status;
}
@ -494,13 +503,28 @@ BOOL freerdp_context_new(freerdp* instance)
instance->autodetect->context = context;
if (!(context->errorDescription = calloc(1, 500)))
{
WLog_ERR(TAG, "calloc failed!");
goto out_error_description;
}
if (!(context->channelErrorEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
goto out_error_create_event;
}
update_register_client_callbacks(rdp->update);
IFCALLRET(instance->ContextNew, ret, instance, instance->context);
if (ret)
return TRUE;
out_error_create_event:
CloseHandle(context->channelErrorEvent);
out_error_description:
free(context->errorDescription);
out_error_graphics_new:
rdp_free(rdp);
out_error_rdp_new:
@ -540,8 +564,12 @@ void freerdp_context_free(freerdp* instance)
metrics_free(instance->context->metrics);
CloseHandle(instance->context->channelErrorEvent);
free(instance->context->errorDescription);
free(instance->context);
instance->context = NULL;
}
UINT32 freerdp_error_info(freerdp* instance)
@ -706,3 +734,33 @@ FREERDP_API ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCoun
context->rdp->transport->written = 0;
return written;
}
FREERDP_API HANDLE getChannelErrorEventHandle(rdpContext* context)
{
return context->channelErrorEvent;
}
FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context)
{
if (WaitForSingleObject( context->channelErrorEvent, 0) == WAIT_OBJECT_0)
{
WLog_ERR(TAG, "%s. Error was %lu", context->errorDescription, context->channelErrorNum);
return FALSE;
}
return TRUE;
}
FREERDP_API WIN32ERROR getChannelError(rdpContext* context)
{
return context->channelErrorNum;
}
FREERDP_API const char* getChannelErrorDescription(rdpContext* context)
{
return context->errorDescription;
}
FREERDP_API void setChannelError(rdpContext* context, WIN32ERROR errorNum, char* description)
{
context->channelErrorNum = errorNum;
strncpy(context->errorDescription, description, 499);
SetEvent(context->channelErrorEvent);
}

View File

@ -55,6 +55,7 @@ static WIN32ERROR mf_peer_audin_receive_samples(audin_server_context* context, c
void mf_peer_audin_init(mfPeerContext* context)
{
context->audin = audin_server_context_new(context->vcm);
context->audin->rdpcontext = &context->_p;
context->audin->data = context;
context->audin->server_formats = supported_audio_formats;

View File

@ -3,6 +3,8 @@
* FreeRDP Mac OS X Server (Audio Output)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -46,12 +48,8 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
//we should actually loop through the list of client formats here
//and see if we can send the client something that it supports...
<<<<<<< HEAD
=======
WLog_DBG(TAG, "Client supports the following %d formats: ", context->num_client_formats);
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
for (i = 0; i < context->num_client_formats; i++)
{
/* TODO: improve the way we agree on a format */
@ -61,10 +59,7 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
(context->client_formats[i].nChannels == context->server_formats[j].nChannels) &&
(context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec))
{
<<<<<<< HEAD
=======
WLog_DBG(TAG, "agreed on format!");
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
formatAgreed = TRUE;
agreedFormat = (AUDIO_FORMAT*)&context->server_formats[j];
break;
@ -77,10 +72,7 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
if (formatAgreed == FALSE)
{
<<<<<<< HEAD
=======
WLog_DBG(TAG, "Could not agree on a audio format with the server");
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
return;
}
@ -123,11 +115,7 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
if (status != noErr)
{
<<<<<<< HEAD
=======
WLog_DBG(TAG, "Failed to create a new Audio Queue. Status code: %d", status);
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
}
UInt32 dataFormatSize = sizeof (recorderState.dataFormat);
@ -164,6 +152,7 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
BOOL mf_peer_rdpsnd_init(mfPeerContext* context)
{
context->rdpsnd = rdpsnd_server_context_new(context->vcm);
context->rdpsnd->rdpcontext = &context->_p;
context->rdpsnd->data = context;
context->rdpsnd->server_formats = supported_audio_formats;
@ -223,11 +212,7 @@ void mf_peer_rdpsnd_input_callback (void *inUserD
if (status != noErr)
{
<<<<<<< HEAD
=======
WLog_DBG(TAG, "AudioQueueEnqueueBuffer() returned status = %d", status);
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
}
}

View File

@ -62,6 +62,7 @@ static WIN32ERROR sf_peer_audin_receive_samples(audin_server_context* context, c
void sf_peer_audin_init(testPeerContext* context)
{
context->audin = audin_server_context_new(context->vcm);
context->audin->rdpcontext = &context->_p;
context->audin->data = context;
context->audin->server_formats = test_audio_formats;

View File

@ -3,6 +3,8 @@
* FreeRDP Sample Server (Lync Multiparty)
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,6 +28,7 @@
BOOL sf_peer_encomsp_init(testPeerContext* context)
{
context->encomsp = encomsp_server_context_new(context->vcm);
context->encomsp->rdpcontext = &context->_p;
if (!context->encomsp)
return FALSE;

View File

@ -3,6 +3,8 @@
* FreeRDP Sample Server (Audio Output)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -43,6 +45,7 @@ static void sf_peer_rdpsnd_activated(RdpsndServerContext* context)
BOOL sf_peer_rdpsnd_init(testPeerContext* context)
{
context->rdpsnd = rdpsnd_server_context_new(context->vcm);
context->rdpsnd->rdpcontext = &context->_p;
context->rdpsnd->data = context;
context->rdpsnd->server_formats = test_audio_formats;
@ -56,7 +59,10 @@ BOOL sf_peer_rdpsnd_init(testPeerContext* context)
context->rdpsnd->Activated = sf_peer_rdpsnd_activated;
context->rdpsnd->Initialize(context->rdpsnd, TRUE);
if (context->rdpsnd->Initialize(context->rdpsnd, TRUE) != CHANNEL_RC_OK)
{
return FALSE;
}
return TRUE;
}

View File

@ -151,6 +151,7 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context)
return FALSE;
context->rdpsnd = rdpsnd_server_context_new(context->vcm);
context->rdpsnd->rdpcontext = &context->_p;
context->rdpsnd->data = context;
context->rdpsnd->server_formats = supported_audio_formats;

View File

@ -2,6 +2,8 @@
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -99,6 +101,8 @@ int shadow_client_encomsp_init(rdpShadowClient* client)
encomsp = client->encomsp = encomsp_server_context_new(client->vcm);
encomsp->rdpcontext = &client->context;
encomsp->custom = (void*) client;
encomsp->ChangeParticipantControlLevel = encomsp_change_participant_control_level;

View File

@ -2,6 +2,8 @@
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,6 +31,7 @@ int shadow_client_remdesk_init(rdpShadowClient* client)
RemdeskServerContext* remdesk;
remdesk = client->remdesk = remdesk_server_context_new(client->vcm);
remdesk->rdpcontext = &client->context;
remdesk->custom = (void*) client;