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:
parent
d9e2834a70
commit
b8c110d19b
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)))
|
||||
{
|
||||
|
@ -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");
|
||||
|
@ -50,7 +50,6 @@ struct cliprdr_plugin
|
||||
BOOL streamFileClipEnabled;
|
||||
BOOL fileClipNoFilePaths;
|
||||
BOOL canLockClipData;
|
||||
WIN32ERROR error;
|
||||
};
|
||||
typedef struct cliprdr_plugin cliprdrPlugin;
|
||||
|
||||
|
@ -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)))
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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)))
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ struct encomsp_plugin
|
||||
void* InitHandle;
|
||||
DWORD OpenHandle;
|
||||
wMessageQueue* queue;
|
||||
WIN32ERROR error;
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
typedef struct encomsp_plugin encomspPlugin;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -49,7 +49,7 @@ struct rail_plugin
|
||||
void* InitHandle;
|
||||
DWORD OpenHandle;
|
||||
wMessageQueue* queue;
|
||||
WIN32ERROR error;
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
typedef struct rail_plugin railPlugin;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
||||
|
||||
|
@ -67,7 +67,7 @@ struct rdpdr_plugin
|
||||
#else
|
||||
HANDLE stopEvent;
|
||||
#endif
|
||||
WIN32ERROR error;
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
WIN32ERROR rdpdr_send(rdpdrPlugin* rdpdr, wStream* s);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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!");
|
||||
|
@ -1381,6 +1381,7 @@ WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
|
||||
gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
|
||||
|
||||
|
||||
context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext));
|
||||
|
||||
if (!context)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -56,7 +56,7 @@ struct remdesk_plugin
|
||||
char* ExpertBlob;
|
||||
BYTE* EncryptedPassStub;
|
||||
int EncryptedPassStubSize;
|
||||
WIN32ERROR error;
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
typedef struct remdesk_plugin remdeskPlugin;
|
||||
|
||||
|
@ -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)))
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -91,6 +91,8 @@ struct _audin_server_context
|
||||
* server must be careful of thread synchronization.
|
||||
*/
|
||||
psAudinServerReceiveSamples ReceiveSamples;
|
||||
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -95,6 +95,8 @@ struct _cliprdr_server_context
|
||||
psCliprdrServerFileContentsRequest ServerFileContentsRequest;
|
||||
psCliprdrClientFileContentsResponse ClientFileContentsResponse;
|
||||
psCliprdrServerFileContentsResponse ServerFileContentsResponse;
|
||||
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -72,6 +72,8 @@ struct _echo_server_context
|
||||
* Receive echo response PDU.
|
||||
*/
|
||||
psEchoServerResponse Response;
|
||||
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -71,6 +71,8 @@ struct _encomsp_server_context
|
||||
psEncomspGraphicsStreamResumed GraphicsStreamResumed;
|
||||
|
||||
EncomspServerPrivate* priv;
|
||||
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -137,6 +137,8 @@ struct _rdpdr_server_context
|
||||
/*** Smartcard callbacks registered by the server. ***/
|
||||
psRdpdrOnSmartcardCreate OnSmartcardCreate;
|
||||
psRdpdrOnSmartcardDelete OnSmartcardDelete;
|
||||
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -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
|
||||
|
@ -47,6 +47,7 @@ struct _remdesk_server_context
|
||||
psRemdeskStop Stop;
|
||||
|
||||
RemdeskServerPrivate* priv;
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user