Reformatted files touched in last 2 commits.

This commit is contained in:
Armin Novak 2016-09-26 12:12:37 +02:00
parent 64590e7e89
commit 9f5da483dc
24 changed files with 2580 additions and 2424 deletions

View File

@ -69,7 +69,8 @@ typedef struct _AudinALSADevice
rdpContext* rdpcontext; rdpContext* rdpcontext;
} AudinALSADevice; } AudinALSADevice;
static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_handle) static BOOL audin_alsa_set_params(AudinALSADevice* alsa,
snd_pcm_t* capture_handle)
{ {
int error; int error;
snd_pcm_hw_params_t* hw_params; snd_pcm_hw_params_t* hw_params;
@ -82,10 +83,13 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand
} }
snd_pcm_hw_params_any(capture_handle, hw_params); snd_pcm_hw_params_any(capture_handle, hw_params);
snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_access(capture_handle, hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(capture_handle, hw_params, alsa->format); snd_pcm_hw_params_set_format(capture_handle, hw_params, alsa->format);
snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &alsa->actual_rate, NULL); snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &alsa->actual_rate,
snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, &alsa->actual_channels); NULL);
snd_pcm_hw_params_set_channels_near(capture_handle, hw_params,
&alsa->actual_channels);
snd_pcm_hw_params(capture_handle, hw_params); snd_pcm_hw_params(capture_handle, hw_params);
snd_pcm_hw_params_free(hw_params); snd_pcm_hw_params_free(hw_params);
snd_pcm_prepare(capture_handle); snd_pcm_prepare(capture_handle);
@ -107,7 +111,8 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size) static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src,
int size)
{ {
int frames; int frames;
int cframes; int cframes;
@ -117,7 +122,6 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
int rbytes_per_frame; int rbytes_per_frame;
int tbytes_per_frame; int tbytes_per_frame;
int status; int status;
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel; tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
@ -157,8 +161,8 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
if (cframes > frames) if (cframes > frames)
cframes = frames; cframes = frames;
CopyMemory(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, src, cframes * tbytes_per_frame); CopyMemory(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, src,
cframes * tbytes_per_frame);
alsa->buffer_frames += cframes; alsa->buffer_frames += cframes;
if (alsa->buffer_frames >= alsa->frames_per_packet) if (alsa->buffer_frames >= alsa->frames_per_packet)
@ -175,7 +179,6 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
encoded_data = alsa->dsp_context->adpcm_buffer; encoded_data = alsa->dsp_context->adpcm_buffer;
encoded_size = alsa->dsp_context->adpcm_size; encoded_size = alsa->dsp_context->adpcm_size;
DEBUG_DVC("encoded %d to %d", DEBUG_DVC("encoded %d to %d",
alsa->buffer_frames * tbytes_per_frame, encoded_size); alsa->buffer_frames * tbytes_per_frame, encoded_size);
} }
@ -226,26 +229,27 @@ static void* audin_alsa_thread_func(void* arg)
snd_pcm_t* capture_handle = NULL; snd_pcm_t* capture_handle = NULL;
AudinALSADevice* alsa = (AudinALSADevice*) arg; AudinALSADevice* alsa = (AudinALSADevice*) arg;
DWORD status; DWORD status;
DEBUG_DVC("in"); DEBUG_DVC("in");
freerdp_channel_init_thread_context(alsa->rdpcontext); freerdp_channel_init_thread_context(alsa->rdpcontext);
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel; tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
buffer = (BYTE*) calloc(1, rbytes_per_frame * alsa->frames_per_packet); buffer = (BYTE*) calloc(1, rbytes_per_frame * alsa->frames_per_packet);
if (!buffer) if (!buffer)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY; error = CHANNEL_RC_NO_MEMORY;
if (alsa->rdpcontext) if (alsa->rdpcontext)
setChannelError(alsa->rdpcontext, error, "calloc failed!"); setChannelError(alsa->rdpcontext, error, "calloc failed!");
goto out; goto out;
} }
freerdp_dsp_context_reset_adpcm(alsa->dsp_context); freerdp_dsp_context_reset_adpcm(alsa->dsp_context);
if ((error = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) if ((error = snd_pcm_open(&capture_handle, alsa->device_name,
SND_PCM_STREAM_CAPTURE, 0)) < 0)
{ {
WLog_ERR(TAG, "snd_pcm_open (%s)", snd_strerror(error)); WLog_ERR(TAG, "snd_pcm_open (%s)", snd_strerror(error));
goto out; goto out;
@ -257,7 +261,7 @@ static void* audin_alsa_thread_func(void* arg)
goto out; goto out;
} }
while(1) while (1)
{ {
status = WaitForSingleObject(alsa->stopEvent, 0); status = WaitForSingleObject(alsa->stopEvent, 0);
@ -289,19 +293,21 @@ static void* audin_alsa_thread_func(void* arg)
WLog_ERR(TAG, "audin_alsa_thread_receive failed with error %lu", error); WLog_ERR(TAG, "audin_alsa_thread_receive failed with error %lu", error);
break; break;
} }
} }
free(buffer); free(buffer);
if (capture_handle) if (capture_handle)
snd_pcm_close(capture_handle); snd_pcm_close(capture_handle);
out: out:
DEBUG_DVC("out"); DEBUG_DVC("out");
if (error && alsa->rdpcontext)
setChannelError(alsa->rdpcontext, error, "audin_alsa_thread_func reported an error");
ExitThread((DWORD)error);
if (error && alsa->rdpcontext)
setChannelError(alsa->rdpcontext, error,
"audin_alsa_thread_func reported an error");
ExitThread((DWORD)error);
return NULL; return NULL;
} }
@ -313,16 +319,14 @@ out:
static UINT audin_alsa_free(IAudinDevice* device) static UINT audin_alsa_free(IAudinDevice* device)
{ {
AudinALSADevice* alsa = (AudinALSADevice*) device; AudinALSADevice* alsa = (AudinALSADevice*) device;
freerdp_dsp_context_free(alsa->dsp_context); freerdp_dsp_context_free(alsa->dsp_context);
free(alsa->device_name); free(alsa->device_name);
free(alsa); free(alsa);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* format) static BOOL audin_alsa_format_supported(IAudinDevice* device,
audinFormat* format)
{ {
switch (format->wFormatTag) switch (format->wFormatTag)
{ {
@ -334,6 +338,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma
{ {
return TRUE; return TRUE;
} }
break; break;
case WAVE_FORMAT_DVI_ADPCM: case WAVE_FORMAT_DVI_ADPCM:
@ -343,6 +348,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma
{ {
return TRUE; return TRUE;
} }
break; break;
} }
@ -354,11 +360,11 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format,
UINT32 FramesPerPacket)
{ {
int bs; int bs;
AudinALSADevice* alsa = (AudinALSADevice*) device; AudinALSADevice* alsa = (AudinALSADevice*) device;
alsa->target_rate = format->nSamplesPerSec; alsa->target_rate = format->nSamplesPerSec;
alsa->actual_rate = format->nSamplesPerSec; alsa->actual_rate = format->nSamplesPerSec;
alsa->target_channels = format->nChannels; alsa->target_channels = format->nChannels;
@ -373,11 +379,13 @@ static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN
alsa->format = SND_PCM_FORMAT_S8; alsa->format = SND_PCM_FORMAT_S8;
alsa->bytes_per_channel = 1; alsa->bytes_per_channel = 1;
break; break;
case 16: case 16:
alsa->format = SND_PCM_FORMAT_S16_LE; alsa->format = SND_PCM_FORMAT_S16_LE;
alsa->bytes_per_channel = 2; alsa->bytes_per_channel = 2;
break; break;
} }
break; break;
case WAVE_FORMAT_DVI_ADPCM: case WAVE_FORMAT_DVI_ADPCM:
@ -401,21 +409,22 @@ static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* user_data) static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive,
void* user_data)
{ {
int tbytes_per_frame; int tbytes_per_frame;
AudinALSADevice* alsa = (AudinALSADevice*) device; AudinALSADevice* alsa = (AudinALSADevice*) device;
alsa->receive = receive; alsa->receive = receive;
alsa->user_data = user_data; alsa->user_data = user_data;
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel; tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
alsa->buffer = (BYTE*) calloc(1, tbytes_per_frame * alsa->frames_per_packet); alsa->buffer = (BYTE*) calloc(1, tbytes_per_frame * alsa->frames_per_packet);
if (!alsa->buffer) if (!alsa->buffer)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
} }
alsa->buffer_frames = 0; alsa->buffer_frames = 0;
if (!(alsa->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) if (!(alsa->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
@ -423,12 +432,14 @@ static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* us
WLog_ERR(TAG, "CreateEvent failed!"); WLog_ERR(TAG, "CreateEvent failed!");
goto error_out; goto error_out;
} }
if (!(alsa->thread = CreateThread(NULL, 0, if (!(alsa->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL))) (LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL)))
{ {
WLog_ERR(TAG, "CreateThread failed!"); WLog_ERR(TAG, "CreateThread failed!");
goto error_out; goto error_out;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
error_out: error_out:
free(alsa->buffer); free(alsa->buffer);
@ -451,6 +462,7 @@ static UINT audin_alsa_close(IAudinDevice* device)
if (alsa->stopEvent) if (alsa->stopEvent)
{ {
SetEvent(alsa->stopEvent); SetEvent(alsa->stopEvent);
if (WaitForSingleObject(alsa->thread, INFINITE) == WAIT_FAILED) if (WaitForSingleObject(alsa->thread, INFINITE) == WAIT_FAILED)
{ {
error = GetLastError(); error = GetLastError();
@ -460,17 +472,14 @@ static UINT audin_alsa_close(IAudinDevice* device)
CloseHandle(alsa->stopEvent); CloseHandle(alsa->stopEvent);
alsa->stopEvent = NULL; alsa->stopEvent = NULL;
CloseHandle(alsa->thread); CloseHandle(alsa->thread);
alsa->thread = NULL; alsa->thread = NULL;
} }
free(alsa->buffer); free(alsa->buffer);
alsa->buffer = NULL; alsa->buffer = NULL;
alsa->receive = NULL; alsa->receive = NULL;
alsa->user_data = NULL; alsa->user_data = NULL;
return error; return error;
} }
@ -485,17 +494,17 @@ COMMAND_LINE_ARGUMENT_A audin_alsa_args[] =
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* args) static UINT audin_alsa_parse_addin_args(AudinALSADevice* device,
ADDIN_ARGV* args)
{ {
int status; int status;
DWORD flags; DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg; COMMAND_LINE_ARGUMENT_A* arg;
AudinALSADevice* alsa = (AudinALSADevice*) device; AudinALSADevice* alsa = (AudinALSADevice*) device;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON |
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_alsa_args, flags, alsa, NULL, NULL); audin_alsa_args, flags, alsa, NULL, NULL);
arg = audin_alsa_args; arg = audin_alsa_args;
do do
@ -504,17 +513,16 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg
continue; continue;
CommandLineSwitchStart(arg) CommandLineSwitchStart(arg)
CommandLineSwitchCase(arg, "dev") CommandLineSwitchCase(arg, "dev")
{ {
alsa->device_name = _strdup(arg->Value); alsa->device_name = _strdup(arg->Value);
if(!alsa->device_name)
if (!alsa->device_name)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
} }
CommandLineSwitchEnd(arg) CommandLineSwitchEnd(arg)
} }
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
@ -533,13 +541,14 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS
pEntryPoints)
{ {
ADDIN_ARGV* args; ADDIN_ARGV* args;
AudinALSADevice* alsa; AudinALSADevice* alsa;
UINT error; UINT error;
alsa = (AudinALSADevice*) calloc(1, sizeof(AudinALSADevice)); alsa = (AudinALSADevice*) calloc(1, sizeof(AudinALSADevice));
if (!alsa) if (!alsa)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -552,7 +561,6 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
alsa->iface.Close = audin_alsa_close; alsa->iface.Close = audin_alsa_close;
alsa->iface.Free = audin_alsa_free; alsa->iface.Free = audin_alsa_free;
alsa->rdpcontext = pEntryPoints->rdpcontext; alsa->rdpcontext = pEntryPoints->rdpcontext;
args = pEntryPoints->args; args = pEntryPoints->args;
if ((error = audin_alsa_parse_addin_args(alsa, args))) if ((error = audin_alsa_parse_addin_args(alsa, args)))
@ -564,6 +572,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
if (!alsa->device_name) if (!alsa->device_name)
{ {
alsa->device_name = _strdup("default"); alsa->device_name = _strdup("default");
if (!alsa->device_name) if (!alsa->device_name)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
@ -579,8 +588,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
alsa->target_channels = 2; alsa->target_channels = 2;
alsa->actual_channels = 2; alsa->actual_channels = 2;
alsa->bytes_per_channel = 2; alsa->bytes_per_channel = 2;
alsa->dsp_context = freerdp_dsp_context_new(); alsa->dsp_context = freerdp_dsp_context_new();
if (!alsa->dsp_context) if (!alsa->dsp_context)
{ {
WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); WLog_ERR(TAG, "freerdp_dsp_context_new failed!");
@ -588,7 +597,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
goto error_out; goto error_out;
} }
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) alsa))) if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin,
(IAudinDevice*) alsa)))
{ {
WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error); WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error);
goto error_out; goto error_out;

View File

@ -81,22 +81,25 @@ static int audin_oss_get_format(audinFormat* format)
switch (format->wFormatTag) switch (format->wFormatTag)
{ {
case WAVE_FORMAT_PCM: case WAVE_FORMAT_PCM:
switch (format->wBitsPerSample) switch (format->wBitsPerSample)
{ {
case 8: case 8:
return AFMT_S8; return AFMT_S8;
case 16: case 16:
return AFMT_S16_LE; return AFMT_S16_LE;
} }
break; break;
case WAVE_FORMAT_ALAW: case WAVE_FORMAT_ALAW:
return AFMT_A_LAW; return AFMT_A_LAW;
#if 0 /* This does not work on my desktop. */ #if 0 /* This does not work on my desktop. */
case WAVE_FORMAT_MULAW: case WAVE_FORMAT_MULAW:
return AFMT_MU_LAW; return AFMT_MU_LAW;
#endif #endif
case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_ADPCM:
case WAVE_FORMAT_DVI_ADPCM: case WAVE_FORMAT_DVI_ADPCM:
return AFMT_S16_LE; return AFMT_S16_LE;
@ -105,7 +108,8 @@ static int audin_oss_get_format(audinFormat* format)
return 0; return 0;
} }
static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* format) static BOOL audin_oss_format_supported(IAudinDevice* device,
audinFormat* format)
{ {
int req_fmt = 0; int req_fmt = 0;
@ -115,7 +119,6 @@ static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* format
switch (format->wFormatTag) switch (format->wFormatTag)
{ {
case WAVE_FORMAT_PCM: case WAVE_FORMAT_PCM:
if (format->cbSize != 0 || if (format->cbSize != 0 ||
format->nSamplesPerSec > 48000 || format->nSamplesPerSec > 48000 ||
(format->wBitsPerSample != 8 && format->wBitsPerSample != 16) || (format->wBitsPerSample != 8 && format->wBitsPerSample != 16) ||
@ -123,9 +126,9 @@ static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* format
return FALSE; return FALSE;
break; break;
case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_ADPCM:
case WAVE_FORMAT_DVI_ADPCM: case WAVE_FORMAT_DVI_ADPCM:
if (format->nSamplesPerSec > 48000 || if (format->nSamplesPerSec > 48000 ||
format->wBitsPerSample != 4 || format->wBitsPerSample != 4 ||
(format->nChannels != 1 && format->nChannels != 2)) (format->nChannels != 1 && format->nChannels != 2))
@ -147,7 +150,8 @@ static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* format
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_oss_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) static UINT audin_oss_set_format(IAudinDevice* device, audinFormat* format,
UINT32 FramesPerPacket)
{ {
AudinOSSDevice* oss = (AudinOSSDevice*)device; AudinOSSDevice* oss = (AudinOSSDevice*)device;
@ -165,6 +169,7 @@ static UINT audin_oss_set_format(IAudinDevice* device, audinFormat* format, UINT
oss->format.wBitsPerSample *= 4; oss->format.wBitsPerSample *= 4;
break; break;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -257,7 +262,8 @@ static void* audin_oss_thread_func(void* arg)
if (ioctl(pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1) if (ioctl(pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno); OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno);
buffer_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8)); buffer_size = (oss->FramesPerPacket * oss->format.nChannels *
(oss->format.wBitsPerSample / 8));
buffer = (BYTE*)calloc((buffer_size + sizeof(void*)), sizeof(BYTE)); buffer = (BYTE*)calloc((buffer_size + sizeof(void*)), sizeof(BYTE));
if (NULL == buffer) if (NULL == buffer)
@ -296,7 +302,8 @@ static void* audin_oss_thread_func(void* arg)
continue; continue;
/* Process. */ /* Process. */
switch (oss->format.wFormatTag) { switch (oss->format.wFormatTag)
{
case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_ADPCM:
if (!oss->dsp_context->encode_ms_adpcm(oss->dsp_context, if (!oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign)) buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
@ -304,9 +311,11 @@ static void* audin_oss_thread_func(void* arg)
error = ERROR_INTERNAL_ERROR; error = ERROR_INTERNAL_ERROR;
goto err_out; goto err_out;
} }
encoded_data = oss->dsp_context->adpcm_buffer; encoded_data = oss->dsp_context->adpcm_buffer;
encoded_size = oss->dsp_context->adpcm_size; encoded_size = oss->dsp_context->adpcm_size;
break; break;
case WAVE_FORMAT_DVI_ADPCM: case WAVE_FORMAT_DVI_ADPCM:
if (!oss->dsp_context->encode_ima_adpcm(oss->dsp_context, if (!oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign)) buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
@ -314,26 +323,29 @@ static void* audin_oss_thread_func(void* arg)
error = ERROR_INTERNAL_ERROR; error = ERROR_INTERNAL_ERROR;
goto err_out; goto err_out;
} }
encoded_data = oss->dsp_context->adpcm_buffer; encoded_data = oss->dsp_context->adpcm_buffer;
encoded_size = oss->dsp_context->adpcm_size; encoded_size = oss->dsp_context->adpcm_size;
break; break;
default: default:
encoded_data = buffer; encoded_data = buffer;
encoded_size = buffer_size; encoded_size = buffer_size;
break; break;
} }
if ((error = oss->receive(encoded_data, encoded_size, oss->user_data))) if ((error = oss->receive(encoded_data, encoded_size, oss->user_data)))
{ {
WLog_ERR(TAG, "oss->receive failed with error %lu", error); WLog_ERR(TAG, "oss->receive failed with error %lu", error);
break; break;
} }
} }
err_out: err_out:
if (error && oss->rdpcontext) if (error && oss->rdpcontext)
setChannelError(oss->rdpcontext, error, "audin_oss_thread_func reported an error"); setChannelError(oss->rdpcontext, error,
"audin_oss_thread_func reported an error");
if (pcm_handle != -1) if (pcm_handle != -1)
{ {
@ -351,9 +363,10 @@ err_out:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_oss_open(IAudinDevice *device, AudinReceive receive, void *user_data) { static UINT audin_oss_open(IAudinDevice* device, AudinReceive receive,
AudinOSSDevice *oss = (AudinOSSDevice*)device; void* user_data)
{
AudinOSSDevice* oss = (AudinOSSDevice*)device;
oss->receive = receive; oss->receive = receive;
oss->user_data = user_data; oss->user_data = user_data;
@ -362,6 +375,7 @@ static UINT audin_oss_open(IAudinDevice *device, AudinReceive receive, void *use
WLog_ERR(TAG, "CreateEvent failed!"); WLog_ERR(TAG, "CreateEvent failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
if (!(oss->thread = CreateThread(NULL, 0, if (!(oss->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL))) (LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL)))
{ {
@ -379,10 +393,10 @@ static UINT audin_oss_open(IAudinDevice *device, AudinReceive receive, void *use
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_oss_close(IAudinDevice *device) static UINT audin_oss_close(IAudinDevice* device)
{ {
UINT error; UINT error;
AudinOSSDevice *oss = (AudinOSSDevice*)device; AudinOSSDevice* oss = (AudinOSSDevice*)device;
if (device == NULL) if (device == NULL)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -390,12 +404,14 @@ static UINT audin_oss_close(IAudinDevice *device)
if (oss->stopEvent != NULL) if (oss->stopEvent != NULL)
{ {
SetEvent(oss->stopEvent); SetEvent(oss->stopEvent);
if (WaitForSingleObject(oss->thread, INFINITE) == WAIT_FAILED) if (WaitForSingleObject(oss->thread, INFINITE) == WAIT_FAILED)
{ {
error = GetLastError(); error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
return error; return error;
} }
CloseHandle(oss->stopEvent); CloseHandle(oss->stopEvent);
oss->stopEvent = NULL; oss->stopEvent = NULL;
CloseHandle(oss->thread); CloseHandle(oss->thread);
@ -404,7 +420,6 @@ static UINT audin_oss_close(IAudinDevice *device)
oss->receive = NULL; oss->receive = NULL;
oss->user_data = NULL; oss->user_data = NULL;
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -415,8 +430,7 @@ static UINT audin_oss_close(IAudinDevice *device)
*/ */
static UINT audin_oss_free(IAudinDevice* device) static UINT audin_oss_free(IAudinDevice* device)
{ {
AudinOSSDevice *oss = (AudinOSSDevice*)device; AudinOSSDevice* oss = (AudinOSSDevice*)device;
int error; int error;
if (device == NULL) if (device == NULL)
@ -426,9 +440,9 @@ static UINT audin_oss_free(IAudinDevice* device)
{ {
WLog_ERR(TAG, "audin_oss_close failed with error code %d!", error); WLog_ERR(TAG, "audin_oss_close failed with error code %d!", error);
} }
freerdp_dsp_context_free(oss->dsp_context); freerdp_dsp_context_free(oss->dsp_context);
free(oss); free(oss);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -443,15 +457,17 @@ COMMAND_LINE_ARGUMENT_A audin_oss_args[] =
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args)
{ {
int status; int status;
char* str_num, *eptr; char* str_num, *eptr;
DWORD flags; DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg; COMMAND_LINE_ARGUMENT_A* arg;
AudinOSSDevice* oss = (AudinOSSDevice*)device; AudinOSSDevice* oss = (AudinOSSDevice*)device;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON |
status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, audin_oss_args, flags, oss, NULL, NULL); COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv,
audin_oss_args, flags, oss, NULL, NULL);
if (status < 0) if (status < 0)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -467,11 +483,13 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
CommandLineSwitchCase(arg, "dev") CommandLineSwitchCase(arg, "dev")
{ {
str_num = _strdup(arg->Value); str_num = _strdup(arg->Value);
if (!str_num) if (!str_num)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
oss->dev_unit = strtol(str_num, &eptr, 10); oss->dev_unit = strtol(str_num, &eptr, 10);
if (oss->dev_unit < 0 || *eptr != '\0') if (oss->dev_unit < 0 || *eptr != '\0')
@ -482,6 +500,7 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
CommandLineSwitchEnd(arg) CommandLineSwitchEnd(arg)
} }
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -496,13 +515,14 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS
pEntryPoints)
{ {
ADDIN_ARGV *args; ADDIN_ARGV* args;
AudinOSSDevice *oss; AudinOSSDevice* oss;
UINT error; UINT error;
oss = (AudinOSSDevice*)calloc(1, sizeof(AudinOSSDevice)); oss = (AudinOSSDevice*)calloc(1, sizeof(AudinOSSDevice));
if (!oss) if (!oss)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -515,7 +535,6 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
oss->iface.Close = audin_oss_close; oss->iface.Close = audin_oss_close;
oss->iface.Free = audin_oss_free; oss->iface.Free = audin_oss_free;
oss->rdpcontext = pEntryPoints->rdpcontext; oss->rdpcontext = pEntryPoints->rdpcontext;
oss->dev_unit = -1; oss->dev_unit = -1;
args = pEntryPoints->args; args = pEntryPoints->args;
@ -526,6 +545,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
} }
oss->dsp_context = freerdp_dsp_context_new(); oss->dsp_context = freerdp_dsp_context_new();
if (!oss->dsp_context) if (!oss->dsp_context)
{ {
WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); WLog_ERR(TAG, "freerdp_dsp_context_new failed!");
@ -533,7 +553,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
goto error_out; goto error_out;
} }
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) oss))) if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin,
(IAudinDevice*) oss)))
{ {
WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error); WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error);
goto error_out; goto error_out;
@ -544,5 +565,4 @@ error_out:
freerdp_dsp_context_free(oss->dsp_context); freerdp_dsp_context_free(oss->dsp_context);
free(oss); free(oss);
return error; return error;
} }

View File

@ -69,13 +69,15 @@ typedef struct _audin_server
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_server_select_format(audin_server_context* context, int client_format_index) static UINT audin_server_select_format(audin_server_context* context,
int client_format_index)
{ {
audin_server* audin = (audin_server*) context; audin_server* audin = (audin_server*) context;
if (client_format_index >= context->num_client_formats) if (client_format_index >= context->num_client_formats)
{ {
WLog_ERR(TAG, "error in protocol: client_format_index >= context->num_client_formats!"); WLog_ERR(TAG,
"error in protocol: client_format_index >= context->num_client_formats!");
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
@ -85,6 +87,7 @@ static UINT audin_server_select_format(audin_server_context* context, int client
{ {
/* TODO: send MSG_SNDIN_FORMATCHANGE */ /* TODO: send MSG_SNDIN_FORMATCHANGE */
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -96,14 +99,16 @@ static UINT audin_server_select_format(audin_server_context* context, int client
static UINT audin_server_send_version(audin_server* audin, wStream* s) static UINT audin_server_send_version(audin_server* audin, wStream* s)
{ {
ULONG written; ULONG written;
Stream_Write_UINT8(s, MSG_SNDIN_VERSION); Stream_Write_UINT8(s, MSG_SNDIN_VERSION);
Stream_Write_UINT32(s, 1); /* Version (4 bytes) */ Stream_Write_UINT32(s, 1); /* Version (4 bytes) */
if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written))
if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s),
Stream_GetPosition(s), &written))
{ {
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -112,13 +117,15 @@ static UINT audin_server_send_version(audin_server* audin, wStream* s)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length) static UINT audin_server_recv_version(audin_server* audin, wStream* s,
UINT32 length)
{ {
UINT32 Version; UINT32 Version;
if (length < 4) if (length < 4)
{ {
WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d", length); WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d",
length);
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
@ -143,11 +150,12 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s)
int i; int i;
UINT32 nAvgBytesPerSec; UINT32 nAvgBytesPerSec;
ULONG written; ULONG written;
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
Stream_Write_UINT8(s, MSG_SNDIN_FORMATS); Stream_Write_UINT8(s, MSG_SNDIN_FORMATS);
Stream_Write_UINT32(s, audin->context.num_server_formats); /* NumFormats (4 bytes) */ Stream_Write_UINT32(s,
Stream_Write_UINT32(s, 0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */ audin->context.num_server_formats); /* NumFormats (4 bytes) */
Stream_Write_UINT32(s,
0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */
for (i = 0; i < audin->context.num_server_formats; i++) for (i = 0; i < audin->context.num_server_formats; i++)
{ {
@ -182,7 +190,8 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s)
} }
} }
return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s),
Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
} }
/** /**
@ -190,29 +199,35 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length) static UINT audin_server_recv_formats(audin_server* audin, wStream* s,
UINT32 length)
{ {
int i; int i;
UINT success = CHANNEL_RC_OK; UINT success = CHANNEL_RC_OK;
if (length < 8) if (length < 8)
{ {
WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %d", length); WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %d",
length);
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
Stream_Read_UINT32(s, audin->context.num_client_formats); /* NumFormats (4 bytes) */ Stream_Read_UINT32(s,
audin->context.num_client_formats); /* NumFormats (4 bytes) */
Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */ Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */
length -= 8; length -= 8;
if (audin->context.num_client_formats <= 0) if (audin->context.num_client_formats <= 0)
{ {
WLog_ERR(TAG, "num_client_formats expected > 0 but got %d", audin->context.num_client_formats); WLog_ERR(TAG, "num_client_formats expected > 0 but got %d",
audin->context.num_client_formats);
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); audin->context.client_formats = malloc(audin->context.num_client_formats *
ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); sizeof(AUDIO_FORMAT));
ZeroMemory(audin->context.client_formats,
audin->context.num_client_formats * sizeof(AUDIO_FORMAT));
for (i = 0; i < audin->context.num_client_formats; i++) for (i = 0; i < audin->context.num_client_formats; i++)
{ {
@ -239,8 +254,10 @@ static UINT audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le
} }
IFCALLRET(audin->context.Opening, success, &audin->context); IFCALLRET(audin->context.Opening, success, &audin->context);
if (success) if (success)
WLog_ERR(TAG, "context.Opening failed with error %lu", success); WLog_ERR(TAG, "context.Opening failed with error %lu", success);
return success; return success;
} }
@ -261,11 +278,12 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s)
} }
audin->opened = TRUE; audin->opened = TRUE;
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
Stream_Write_UINT8(s, MSG_SNDIN_OPEN); Stream_Write_UINT8(s, MSG_SNDIN_OPEN);
Stream_Write_UINT32(s, audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */ Stream_Write_UINT32(s,
Stream_Write_UINT32(s, audin->context.selected_client_format); /* initialFormat (4 bytes) */ audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */
Stream_Write_UINT32(s,
audin->context.selected_client_format); /* initialFormat (4 bytes) */
/* /*
* [MS-RDPEAI] 3.2.5.1.6 * [MS-RDPEAI] 3.2.5.1.6
* The second format specify the format that SHOULD be used to capture data from * The second format specify the format that SHOULD be used to capture data from
@ -278,8 +296,8 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s)
Stream_Write_UINT16(s, 4); /* nBlockAlign */ Stream_Write_UINT16(s, 4); /* nBlockAlign */
Stream_Write_UINT16(s, 16); /* wBitsPerSample */ Stream_Write_UINT16(s, 16); /* wBitsPerSample */
Stream_Write_UINT16(s, 0); /* cbSize */ Stream_Write_UINT16(s, 0); /* cbSize */
return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s),
return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
} }
/** /**
@ -287,20 +305,20 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length) static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s,
UINT32 length)
{ {
UINT32 Result; UINT32 Result;
UINT success = CHANNEL_RC_OK; UINT success = CHANNEL_RC_OK;
if (length < 4) if (length < 4)
{ {
WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d", length); WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d",
length);
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
Stream_Read_UINT32(s, Result); Stream_Read_UINT32(s, Result);
IFCALLRET(audin->context.OpenResult, success, &audin->context, Result); IFCALLRET(audin->context.OpenResult, success, &audin->context, Result);
if (success) if (success)
@ -314,7 +332,8 @@ static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 length) static UINT audin_server_recv_data(audin_server* audin, wStream* s,
UINT32 length)
{ {
AUDIO_FORMAT* format; AUDIO_FORMAT* format;
int sbytes_per_sample; int sbytes_per_sample;
@ -359,7 +378,8 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt
sbytes_per_frame = format->nChannels * sbytes_per_sample; sbytes_per_frame = format->nChannels * sbytes_per_sample;
} }
if (format->nSamplesPerSec == audin->context.dst_format.nSamplesPerSec && format->nChannels == audin->context.dst_format.nChannels) if (format->nSamplesPerSec == audin->context.dst_format.nSamplesPerSec
&& format->nChannels == audin->context.dst_format.nChannels)
{ {
frames = size / sbytes_per_frame; frames = size / sbytes_per_frame;
} }
@ -393,13 +413,13 @@ static void* audin_server_thread_func(void* arg)
audin_server* audin = (audin_server*) arg; audin_server* audin = (audin_server*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
DWORD status; DWORD status;
buffer = NULL; buffer = NULL;
BytesReturned = 0; BytesReturned = 0;
ChannelEvent = NULL; ChannelEvent = NULL;
freerdp_channel_init_thread_context(audin->context.rdpcontext); freerdp_channel_init_thread_context(audin->context.rdpcontext);
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualEventHandle, &buffer,
&BytesReturned) == TRUE)
{ {
if (BytesReturned == sizeof(HANDLE)) if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
@ -421,7 +441,8 @@ static void* audin_server_thread_func(void* arg)
while (1) while (1)
{ {
if ((status = WaitForMultipleObjects(nCount, events, FALSE, 100)) == WAIT_OBJECT_0) if ((status = WaitForMultipleObjects(nCount, events, FALSE,
100)) == WAIT_OBJECT_0)
goto out; goto out;
if (status == WAIT_FAILED) if (status == WAIT_FAILED)
@ -431,7 +452,8 @@ static void* audin_server_thread_func(void* arg)
goto out; goto out;
} }
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady,
&buffer, &BytesReturned) == FALSE)
{ {
WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); WLog_ERR(TAG, "WTSVirtualChannelQuery failed");
error = ERROR_INTERNAL_ERROR; error = ERROR_INTERNAL_ERROR;
@ -439,7 +461,6 @@ static void* audin_server_thread_func(void* arg)
} }
ready = *((BOOL*) buffer); ready = *((BOOL*) buffer);
WTSFreeMemory(buffer); WTSFreeMemory(buffer);
if (ready) if (ready)
@ -447,6 +468,7 @@ static void* audin_server_thread_func(void* arg)
} }
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -454,7 +476,6 @@ static void* audin_server_thread_func(void* arg)
goto out; goto out;
} }
if (ready) if (ready)
{ {
if ((error = audin_server_send_version(audin, s))) if ((error = audin_server_send_version(audin, s)))
@ -466,7 +487,8 @@ static void* audin_server_thread_func(void* arg)
while (ready) while (ready)
{ {
if ((status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE)) == WAIT_OBJECT_0) if ((status = WaitForMultipleObjects(nCount, events, FALSE,
INFINITE)) == WAIT_OBJECT_0)
break; break;
if (status == WAIT_FAILED) if (status == WAIT_FAILED)
@ -484,10 +506,13 @@ static void* audin_server_thread_func(void* arg)
error = ERROR_INTERNAL_ERROR; error = ERROR_INTERNAL_ERROR;
break; break;
} }
if (BytesReturned < 1) if (BytesReturned < 1)
continue; continue;
if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
break; break;
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s), if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned) == FALSE) Stream_Capacity(s), &BytesReturned) == FALSE)
{ {
@ -507,11 +532,13 @@ static void* audin_server_thread_func(void* arg)
WLog_ERR(TAG, "audin_server_recv_version failed with error %lu!", error); WLog_ERR(TAG, "audin_server_recv_version failed with error %lu!", error);
goto out_capacity; goto out_capacity;
} }
if ((error = audin_server_send_formats(audin, s))) if ((error = audin_server_send_formats(audin, s)))
{ {
WLog_ERR(TAG, "audin_server_send_formats failed with error %lu!", error); WLog_ERR(TAG, "audin_server_send_formats failed with error %lu!", error);
goto out_capacity; goto out_capacity;
} }
break; break;
case MSG_SNDIN_FORMATS: case MSG_SNDIN_FORMATS:
@ -520,11 +547,13 @@ static void* audin_server_thread_func(void* arg)
WLog_ERR(TAG, "audin_server_recv_formats failed with error %lu!", error); WLog_ERR(TAG, "audin_server_recv_formats failed with error %lu!", error);
goto out_capacity; goto out_capacity;
} }
if ((error = audin_server_send_open(audin, s))) if ((error = audin_server_send_open(audin, s)))
{ {
WLog_ERR(TAG, "audin_server_send_open failed with error %lu!", error); WLog_ERR(TAG, "audin_server_send_open failed with error %lu!", error);
goto out_capacity; goto out_capacity;
} }
break; break;
case MSG_SNDIN_OPEN_REPLY: case MSG_SNDIN_OPEN_REPLY:
@ -533,6 +562,7 @@ static void* audin_server_thread_func(void* arg)
WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %lu!", error); WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %lu!", error);
goto out_capacity; goto out_capacity;
} }
break; break;
case MSG_SNDIN_DATA_INCOMING: case MSG_SNDIN_DATA_INCOMING:
@ -544,6 +574,7 @@ static void* audin_server_thread_func(void* arg)
WLog_ERR(TAG, "audin_server_recv_data failed with error %lu!", error); WLog_ERR(TAG, "audin_server_recv_data failed with error %lu!", error);
goto out_capacity; goto out_capacity;
}; };
break; break;
case MSG_SNDIN_FORMATCHANGE: case MSG_SNDIN_FORMATCHANGE:
@ -560,8 +591,10 @@ out_capacity:
out: out:
WTSVirtualChannelClose(audin->audin_channel); WTSVirtualChannelClose(audin->audin_channel);
audin->audin_channel = NULL; audin->audin_channel = NULL;
if (error && audin->context.rdpcontext) if (error && audin->context.rdpcontext)
setChannelError(audin->context.rdpcontext, error, "audin_server_thread_func reported an error"); setChannelError(audin->context.rdpcontext, error,
"audin_server_thread_func reported an error");
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
@ -575,13 +608,12 @@ static BOOL audin_server_open(audin_server_context* context)
{ {
PULONG pSessionId = NULL; PULONG pSessionId = NULL;
DWORD BytesReturned = 0; DWORD BytesReturned = 0;
audin->SessionId = WTS_CURRENT_SESSION; audin->SessionId = WTS_CURRENT_SESSION;
if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION,
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned)) WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned))
{ {
audin->SessionId = (DWORD) *pSessionId; audin->SessionId = (DWORD) * pSessionId;
WTSFreeMemory(pSessionId); WTSFreeMemory(pSessionId);
} }
@ -611,6 +643,7 @@ static BOOL audin_server_open(audin_server_context* context)
return TRUE; return TRUE;
} }
WLog_ERR(TAG, "thread already running!"); WLog_ERR(TAG, "thread already running!");
return FALSE; return FALSE;
} }
@ -622,6 +655,7 @@ static BOOL audin_server_close(audin_server_context* context)
if (audin->thread) if (audin->thread)
{ {
SetEvent(audin->stopEvent); SetEvent(audin->stopEvent);
if (WaitForSingleObject(audin->thread, INFINITE) == WAIT_FAILED) if (WaitForSingleObject(audin->thread, INFINITE) == WAIT_FAILED)
{ {
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", GetLastError()); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", GetLastError());
@ -641,15 +675,14 @@ static BOOL audin_server_close(audin_server_context* context)
} }
audin->context.selected_client_format = -1; audin->context.selected_client_format = -1;
return TRUE; return TRUE;
} }
audin_server_context* audin_server_context_new(HANDLE vcm) audin_server_context* audin_server_context_new(HANDLE vcm)
{ {
audin_server* audin; audin_server* audin;
audin = (audin_server*)calloc(1, sizeof(audin_server));
audin = (audin_server *)calloc(1, sizeof(audin_server));
if (!audin) if (!audin)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -662,7 +695,6 @@ audin_server_context* audin_server_context_new(HANDLE vcm)
audin->context.SelectFormat = audin_server_select_format; audin->context.SelectFormat = audin_server_select_format;
audin->context.Open = audin_server_open; audin->context.Open = audin_server_open;
audin->context.Close = audin_server_close; audin->context.Close = audin_server_close;
audin->dsp_context = freerdp_dsp_context_new(); audin->dsp_context = freerdp_dsp_context_new();
if (!audin->dsp_context) if (!audin->dsp_context)
@ -678,7 +710,6 @@ audin_server_context* audin_server_context_new(HANDLE vcm)
void audin_server_context_free(audin_server_context* context) void audin_server_context_free(audin_server_context* context)
{ {
audin_server* audin = (audin_server*) context; audin_server* audin = (audin_server*) context;
audin_server_close(context); audin_server_close(context);
if (audin->dsp_context) if (audin->dsp_context)

View File

@ -1052,7 +1052,6 @@ static void* cliprdr_virtual_channel_client_thread(void* arg)
wMessage message; wMessage message;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) arg; cliprdrPlugin* cliprdr = (cliprdrPlugin*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(cliprdr->context->rdpcontext); freerdp_channel_init_thread_context(cliprdr->context->rdpcontext);
while (1) while (1)
@ -1298,6 +1297,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{ {
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]", WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc); WTSErrorToString(rc), rc);
if (context) if (context)
*(pEntryPointsEx->ppInterface) = NULL; *(pEntryPointsEx->ppInterface) = NULL;

File diff suppressed because it is too large Load Diff

View File

@ -1519,6 +1519,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{ {
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]", WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc); WTSErrorToString(rc), rc);
if (context) if (context)
*(pEntryPointsEx->ppInterface) = NULL; *(pEntryPointsEx->ppInterface) = NULL;

View File

@ -45,15 +45,13 @@ static void* drdynvc_server_thread(void* arg)
DWORD BytesReturned; DWORD BytesReturned;
DrdynvcServerContext* context; DrdynvcServerContext* context;
UINT error = ERROR_INTERNAL_ERROR; UINT error = ERROR_INTERNAL_ERROR;
context = (DrdynvcServerContext*) arg; context = (DrdynvcServerContext*) arg;
buffer = NULL; buffer = NULL;
BytesReturned = 0; BytesReturned = 0;
ChannelEvent = NULL; ChannelEvent = NULL;
freerdp_channel_init_thread_context(context->rdpcontext); freerdp_channel_init_thread_context(context->rdpcontext);
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -61,7 +59,8 @@ static void* drdynvc_server_thread(void* arg)
return NULL; return NULL;
} }
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
&buffer, &BytesReturned) == TRUE)
{ {
if (BytesReturned == sizeof(HANDLE)) if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
@ -83,13 +82,16 @@ static void* drdynvc_server_thread(void* arg)
break; break;
} }
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned)) if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0,
&BytesReturned))
{ {
WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
break; break;
} }
if (BytesReturned < 1) if (BytesReturned < 1)
continue; continue;
if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
@ -119,7 +121,8 @@ static void* drdynvc_server_thread(void* arg)
*/ */
static UINT drdynvc_server_start(DrdynvcServerContext* context) static UINT drdynvc_server_start(DrdynvcServerContext* context)
{ {
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "drdynvc"); context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm,
WTS_CURRENT_SESSION, "drdynvc");
if (!context->priv->ChannelHandle) if (!context->priv->ChannelHandle)
{ {
@ -132,6 +135,7 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context)
WLog_ERR(TAG, "CreateEvent failed!"); WLog_ERR(TAG, "CreateEvent failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
if (!(context->priv->Thread = CreateThread(NULL, 0, if (!(context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL))) (LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL)))
{ {
@ -160,25 +164,23 @@ static UINT drdynvc_server_stop(DrdynvcServerContext* context)
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error; return error;
} }
CloseHandle(context->priv->Thread);
CloseHandle(context->priv->Thread);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm) DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm)
{ {
DrdynvcServerContext* context; DrdynvcServerContext* context;
context = (DrdynvcServerContext*) calloc(1, sizeof(DrdynvcServerContext)); context = (DrdynvcServerContext*) calloc(1, sizeof(DrdynvcServerContext));
if (context) if (context)
{ {
context->vcm = vcm; context->vcm = vcm;
context->Start = drdynvc_server_start; context->Start = drdynvc_server_start;
context->Stop = drdynvc_server_stop; context->Stop = drdynvc_server_stop;
context->priv = (DrdynvcServerPrivate*) calloc(1, sizeof(DrdynvcServerPrivate)); context->priv = (DrdynvcServerPrivate*) calloc(1, sizeof(DrdynvcServerPrivate));
if (!context->priv) if (!context->priv)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");

View File

@ -80,15 +80,19 @@ static UINT32 drive_map_posix_err(int fs_errno)
case EACCES: case EACCES:
rc = STATUS_ACCESS_DENIED; rc = STATUS_ACCESS_DENIED;
break; break;
case ENOENT: case ENOENT:
rc = STATUS_NO_SUCH_FILE; rc = STATUS_NO_SUCH_FILE;
break; break;
case EBUSY: case EBUSY:
rc = STATUS_DEVICE_BUSY; rc = STATUS_DEVICE_BUSY;
break; break;
case EEXIST: case EEXIST:
rc = STATUS_OBJECT_NAME_COLLISION; rc = STATUS_OBJECT_NAME_COLLISION;
break; break;
case EISDIR: case EISDIR:
rc = STATUS_FILE_IS_A_DIRECTORY; rc = STATUS_FILE_IS_A_DIRECTORY;
break; break;
@ -104,10 +108,8 @@ static UINT32 drive_map_posix_err(int fs_errno)
static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id) static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id)
{ {
DRIVE_FILE* file = NULL; DRIVE_FILE* file = NULL;
void* key = (void*) (size_t) id; void* key = (void*)(size_t) id;
file = (DRIVE_FILE*) ListDictionary_GetItemValue(drive->files, key); file = (DRIVE_FILE*) ListDictionary_GetItemValue(drive->files, key);
return file; return file;
} }
@ -128,19 +130,19 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
UINT32 CreateOptions; UINT32 CreateOptions;
UINT32 PathLength; UINT32 PathLength;
char* path = NULL; char* path = NULL;
Stream_Read_UINT32(irp->input, DesiredAccess); Stream_Read_UINT32(irp->input, DesiredAccess);
Stream_Seek(irp->input, 16); /* AllocationSize(8), FileAttributes(4), SharedAccess(4) */ Stream_Seek(irp->input,
16); /* AllocationSize(8), FileAttributes(4), SharedAccess(4) */
Stream_Read_UINT32(irp->input, CreateDisposition); Stream_Read_UINT32(irp->input, CreateDisposition);
Stream_Read_UINT32(irp->input, CreateOptions); Stream_Read_UINT32(irp->input, CreateOptions);
Stream_Read_UINT32(irp->input, PathLength); Stream_Read_UINT32(irp->input, PathLength);
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input), status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
PathLength / 2, &path, 0, NULL, NULL); PathLength / 2, &path, 0, NULL, NULL);
if (status < 1) if (status < 1)
{ {
path = (char*) calloc(1, 1); path = (char*) calloc(1, 1);
if (!path) if (!path)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -148,9 +150,7 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
} }
} }
FileId = irp->devman->id_sequence++; FileId = irp->devman->id_sequence++;
file = drive_file_new(drive->path, path, FileId, file = drive_file_new(drive->path, path, FileId,
DesiredAccess, CreateDisposition, CreateOptions); DesiredAccess, CreateDisposition, CreateOptions);
@ -164,14 +164,14 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
{ {
FileId = 0; FileId = 0;
Information = 0; Information = 0;
/* map errno to windows result */ /* map errno to windows result */
irp->IoStatus = drive_map_posix_err(file->err); irp->IoStatus = drive_map_posix_err(file->err);
drive_file_free(file); drive_file_free(file);
} }
else else
{ {
key = (void*) (size_t) file->id; key = (void*)(size_t) file->id;
if (!ListDictionary_Add(drive->files, key, file)) if (!ListDictionary_Add(drive->files, key, file))
{ {
WLog_ERR(TAG, "ListDictionary_Add failed!"); WLog_ERR(TAG, "ListDictionary_Add failed!");
@ -187,12 +187,15 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
case FILE_OVERWRITE: case FILE_OVERWRITE:
Information = FILE_SUPERSEDED; Information = FILE_SUPERSEDED;
break; break;
case FILE_OPEN_IF: case FILE_OPEN_IF:
Information = FILE_OPENED; Information = FILE_OPENED;
break; break;
case FILE_OVERWRITE_IF: case FILE_OVERWRITE_IF:
Information = FILE_OVERWRITTEN; Information = FILE_OVERWRITTEN;
break; break;
default: default:
Information = 0; Information = 0;
break; break;
@ -201,9 +204,7 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
Stream_Write_UINT32(irp->output, FileId); Stream_Write_UINT32(irp->output, FileId);
Stream_Write_UINT8(irp->output, Information); Stream_Write_UINT8(irp->output, Information);
free(path); free(path);
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -216,10 +217,8 @@ static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
{ {
void* key; void* key;
DRIVE_FILE* file; DRIVE_FILE* file;
file = drive_get_file_by_id(drive, irp->FileId); file = drive_get_file_by_id(drive, irp->FileId);
key = (void*)(size_t) irp->FileId;
key = (void*) (size_t) irp->FileId;
if (!file) if (!file)
{ {
@ -232,7 +231,6 @@ static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
} }
Stream_Zero(irp->output, 5); /* Padding(5) */ Stream_Zero(irp->output, 5); /* Padding(5) */
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -247,10 +245,8 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
UINT32 Length; UINT32 Length;
UINT64 Offset; UINT64 Offset;
BYTE* buffer = NULL; BYTE* buffer = NULL;
Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset); Stream_Read_UINT64(irp->input, Offset);
file = drive_get_file_by_id(drive, irp->FileId); file = drive_get_file_by_id(drive, irp->FileId);
if (!file) if (!file)
@ -266,6 +262,7 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
else else
{ {
buffer = (BYTE*) malloc(Length); buffer = (BYTE*) malloc(Length);
if (!buffer) if (!buffer)
{ {
WLog_ERR(TAG, "malloc failed!"); WLog_ERR(TAG, "malloc failed!");
@ -290,11 +287,11 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
Stream_Write(irp->output, buffer, Length); Stream_Write(irp->output, buffer, Length);
} }
free(buffer); free(buffer);
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -308,11 +305,9 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
DRIVE_FILE* file; DRIVE_FILE* file;
UINT32 Length; UINT32 Length;
UINT64 Offset; UINT64 Offset;
Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset); Stream_Read_UINT64(irp->input, Offset);
Stream_Seek(irp->input, 20); /* Padding */ Stream_Seek(irp->input, 20); /* Padding */
file = drive_get_file_by_id(drive, irp->FileId); file = drive_get_file_by_id(drive, irp->FileId);
if (!file) if (!file)
@ -333,7 +328,6 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT32(irp->output, Length);
Stream_Write_UINT8(irp->output, 0); /* Padding */ Stream_Write_UINT8(irp->output, 0); /* Padding */
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -346,9 +340,7 @@ static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
{ {
DRIVE_FILE* file; DRIVE_FILE* file;
UINT32 FsInformationClass; UINT32 FsInformationClass;
Stream_Read_UINT32(irp->input, FsInformationClass); Stream_Read_UINT32(irp->input, FsInformationClass);
file = drive_get_file_by_id(drive, irp->FileId); file = drive_get_file_by_id(drive, irp->FileId);
if (!file) if (!file)
@ -373,18 +365,17 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
DRIVE_FILE* file; DRIVE_FILE* file;
UINT32 FsInformationClass; UINT32 FsInformationClass;
UINT32 Length; UINT32 Length;
Stream_Read_UINT32(irp->input, FsInformationClass); Stream_Read_UINT32(irp->input, FsInformationClass);
Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT32(irp->input, Length);
Stream_Seek(irp->input, 24); /* Padding */ Stream_Seek(irp->input, 24); /* Padding */
file = drive_get_file_by_id(drive, irp->FileId); file = drive_get_file_by_id(drive, irp->FileId);
if (!file) if (!file)
{ {
irp->IoStatus = STATUS_UNSUCCESSFUL; irp->IoStatus = STATUS_UNSUCCESSFUL;
} }
else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input)) else if (!drive_file_set_information(file, FsInformationClass, Length,
irp->input))
{ {
irp->IoStatus = STATUS_UNSUCCESSFUL; irp->IoStatus = STATUS_UNSUCCESSFUL;
} }
@ -393,7 +384,6 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
irp->IoStatus = STATUS_DIRECTORY_NOT_EMPTY; irp->IoStatus = STATUS_DIRECTORY_NOT_EMPTY;
Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT32(irp->output, Length);
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -402,7 +392,8 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp) static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive,
IRP* irp)
{ {
UINT32 FsInformationClass; UINT32 FsInformationClass;
wStream* output = irp->output; wStream* output = irp->output;
@ -412,9 +403,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
char* diskType = {"FAT32"}; char* diskType = {"FAT32"};
WCHAR* outStr = NULL; WCHAR* outStr = NULL;
int length; int length;
Stream_Read_UINT32(irp->input, FsInformationClass); Stream_Read_UINT32(irp->input, FsInformationClass);
STATVFS(drive->path, &svfst); STATVFS(drive->path, &svfst);
STAT(drive->path, &st); STAT(drive->path, &st);
@ -424,6 +413,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
/* http://msdn.microsoft.com/en-us/library/cc232108.aspx */ /* http://msdn.microsoft.com/en-us/library/cc232108.aspx */
length = ConvertToUnicode(sys_code_page, 0, volumeLabel, -1, &outStr, 0) * 2; length = ConvertToUnicode(sys_code_page, 0, volumeLabel, -1, &outStr, 0) * 2;
Stream_Write_UINT32(output, 17 + length); /* Length */ Stream_Write_UINT32(output, 17 + length); /* Length */
if (!Stream_EnsureRemainingCapacity(output, 17 + length)) if (!Stream_EnsureRemainingCapacity(output, 17 + length))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
@ -431,7 +421,8 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* VolumeCreationTime */ Stream_Write_UINT64(output,
FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* VolumeCreationTime */
#ifdef ANDROID #ifdef ANDROID
Stream_Write_UINT32(output, svfst.f_fsid.__val[0]); /* VolumeSerialNumber */ Stream_Write_UINT32(output, svfst.f_fsid.__val[0]); /* VolumeSerialNumber */
#else #else
@ -447,11 +438,13 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
case FileFsSizeInformation: case FileFsSizeInformation:
/* http://msdn.microsoft.com/en-us/library/cc232107.aspx */ /* http://msdn.microsoft.com/en-us/library/cc232107.aspx */
Stream_Write_UINT32(output, 24); /* Length */ Stream_Write_UINT32(output, 24); /* Length */
if (!Stream_EnsureRemainingCapacity(output, 24)) if (!Stream_EnsureRemainingCapacity(output, 24))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */ Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */
Stream_Write_UINT64(output, svfst.f_bavail); /* AvailableAllocationUnits */ Stream_Write_UINT64(output, svfst.f_bavail); /* AvailableAllocationUnits */
Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */ Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */
@ -462,11 +455,13 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
/* http://msdn.microsoft.com/en-us/library/cc232101.aspx */ /* http://msdn.microsoft.com/en-us/library/cc232101.aspx */
length = ConvertToUnicode(sys_code_page, 0, diskType, -1, &outStr, 0) * 2; length = ConvertToUnicode(sys_code_page, 0, diskType, -1, &outStr, 0) * 2;
Stream_Write_UINT32(output, 12 + length); /* Length */ Stream_Write_UINT32(output, 12 + length); /* Length */
if (!Stream_EnsureRemainingCapacity(output, 12 + length)) if (!Stream_EnsureRemainingCapacity(output, 12 + length))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Write_UINT32(output, Stream_Write_UINT32(output,
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_SENSITIVE_SEARCH |
FILE_CASE_PRESERVED_NAMES | FILE_CASE_PRESERVED_NAMES |
@ -474,7 +469,8 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
#ifdef ANDROID #ifdef ANDROID
Stream_Write_UINT32(output, 255); /* MaximumComponentNameLength */ Stream_Write_UINT32(output, 255); /* MaximumComponentNameLength */
#else #else
Stream_Write_UINT32(output, svfst.f_namemax/*510*/); /* MaximumComponentNameLength */ Stream_Write_UINT32(output,
svfst.f_namemax/*510*/); /* MaximumComponentNameLength */
#endif #endif
Stream_Write_UINT32(output, length); /* FileSystemNameLength */ Stream_Write_UINT32(output, length); /* FileSystemNameLength */
Stream_Write(output, outStr, length); /* FileSystemName (Unicode) */ Stream_Write(output, outStr, length); /* FileSystemName (Unicode) */
@ -484,13 +480,16 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
case FileFsFullSizeInformation: case FileFsFullSizeInformation:
/* http://msdn.microsoft.com/en-us/library/cc232104.aspx */ /* http://msdn.microsoft.com/en-us/library/cc232104.aspx */
Stream_Write_UINT32(output, 32); /* Length */ Stream_Write_UINT32(output, 32); /* Length */
if (!Stream_EnsureRemainingCapacity(output, 32)) if (!Stream_EnsureRemainingCapacity(output, 32))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */ Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */
Stream_Write_UINT64(output, svfst.f_bavail); /* CallerAvailableAllocationUnits */ Stream_Write_UINT64(output,
svfst.f_bavail); /* CallerAvailableAllocationUnits */
Stream_Write_UINT64(output, svfst.f_bfree); /* AvailableAllocationUnits */ Stream_Write_UINT64(output, svfst.f_bfree); /* AvailableAllocationUnits */
Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */ Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */
Stream_Write_UINT32(output, svfst.f_bsize); /* BytesPerSector */ Stream_Write_UINT32(output, svfst.f_bsize); /* BytesPerSector */
@ -499,11 +498,13 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
case FileFsDeviceInformation: case FileFsDeviceInformation:
/* http://msdn.microsoft.com/en-us/library/cc232109.aspx */ /* http://msdn.microsoft.com/en-us/library/cc232109.aspx */
Stream_Write_UINT32(output, 8); /* Length */ Stream_Write_UINT32(output, 8); /* Length */
if (!Stream_EnsureRemainingCapacity(output, 8)) if (!Stream_EnsureRemainingCapacity(output, 8))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Write_UINT32(output, FILE_DEVICE_DISK); /* DeviceType */ Stream_Write_UINT32(output, FILE_DEVICE_DISK); /* DeviceType */
Stream_Write_UINT32(output, 0); /* Characteristics */ Stream_Write_UINT32(output, 0); /* Characteristics */
break; break;
@ -528,11 +529,8 @@ static UINT drive_process_irp_silent_ignore(DRIVE_DEVICE* drive, IRP* irp)
{ {
UINT32 FsInformationClass; UINT32 FsInformationClass;
wStream* output = irp->output; wStream* output = irp->output;
Stream_Read_UINT32(irp->input, FsInformationClass); Stream_Read_UINT32(irp->input, FsInformationClass);
Stream_Write_UINT32(output, 0); /* Length */ Stream_Write_UINT32(output, 0); /* Length */
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -549,12 +547,10 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
BYTE InitialQuery; BYTE InitialQuery;
UINT32 PathLength; UINT32 PathLength;
UINT32 FsInformationClass; UINT32 FsInformationClass;
Stream_Read_UINT32(irp->input, FsInformationClass); Stream_Read_UINT32(irp->input, FsInformationClass);
Stream_Read_UINT8(irp->input, InitialQuery); Stream_Read_UINT8(irp->input, InitialQuery);
Stream_Read_UINT32(irp->input, PathLength); Stream_Read_UINT32(irp->input, PathLength);
Stream_Seek(irp->input, 23); /* Padding */ Stream_Seek(irp->input, 23); /* Padding */
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input), status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
PathLength / 2, &path, 0, NULL, NULL); PathLength / 2, &path, 0, NULL, NULL);
@ -572,13 +568,13 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
irp->IoStatus = STATUS_UNSUCCESSFUL; irp->IoStatus = STATUS_UNSUCCESSFUL;
Stream_Write_UINT32(irp->output, 0); /* Length */ Stream_Write_UINT32(irp->output, 0); /* Length */
} }
else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, irp->output)) else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery,
path, irp->output))
{ {
irp->IoStatus = STATUS_NO_MORE_FILES; irp->IoStatus = STATUS_NO_MORE_FILES;
} }
free(path); free(path);
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -605,6 +601,7 @@ static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
return irp->Complete(irp); return irp->Complete(irp);
break; break;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -627,7 +624,6 @@ static UINT drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp)
static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp) static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
{ {
UINT error; UINT error;
irp->IoStatus = STATUS_SUCCESS; irp->IoStatus = STATUS_SUCCESS;
switch (irp->MajorFunction) switch (irp->MajorFunction)
@ -677,6 +673,7 @@ static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
error = irp->Complete(irp); error = irp->Complete(irp);
break; break;
} }
return error; return error;
} }
@ -686,8 +683,8 @@ static void* drive_thread_func(void* arg)
wMessage message; wMessage message;
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg; DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(drive->rdpcontext); freerdp_channel_init_thread_context(drive->rdpcontext);
while (1) while (1)
{ {
if (!MessageQueue_Wait(drive->IrpQueue)) if (!MessageQueue_Wait(drive->IrpQueue))
@ -718,7 +715,9 @@ static void* drive_thread_func(void* arg)
} }
if (error && drive->rdpcontext) if (error && drive->rdpcontext)
setChannelError(drive->rdpcontext, error, "drive_thread_func reported an error"); setChannelError(drive->rdpcontext, error,
"drive_thread_func reported an error");
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
} }
@ -731,11 +730,13 @@ static void* drive_thread_func(void* arg)
static UINT drive_irp_request(DEVICE* device, IRP* irp) static UINT drive_irp_request(DEVICE* device, IRP* irp)
{ {
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device; DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
if (!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!"); WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -749,7 +750,8 @@ static UINT drive_free(DEVICE* device)
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device; DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
if (MessageQueue_PostQuit(drive->IrpQueue, 0) && (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED)) if (MessageQueue_PostQuit(drive->IrpQueue, 0)
&& (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
{ {
error = GetLastError(); error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
@ -757,12 +759,9 @@ static UINT drive_free(DEVICE* device)
} }
CloseHandle(drive->thread); CloseHandle(drive->thread);
ListDictionary_Free(drive->files); ListDictionary_Free(drive->files);
MessageQueue_Free(drive->IrpQueue); MessageQueue_Free(drive->IrpQueue);
Stream_Free(drive->device.data, TRUE); Stream_Free(drive->device.data, TRUE);
free(drive); free(drive);
return error; return error;
} }
@ -772,29 +771,32 @@ static UINT drive_free(DEVICE* device)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* name, char* path) UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
char* name, char* path)
{ {
int i, length; int i, length;
DRIVE_DEVICE* drive; DRIVE_DEVICE* drive;
UINT error; UINT error;
#ifdef WIN32 #ifdef WIN32
/* /*
* We cannot enter paths like c:\ because : is an arg separator * We cannot enter paths like c:\ because : is an arg separator
* thus, paths are entered as c+\ and the + is substituted here * thus, paths are entered as c+\ and the + is substituted here
*/ */
if (path[1] == '+') if (path[1] == '+')
{ {
if ((path[0]>='a' && path[0]<='z') || (path[0]>='A' && path[0]<='Z')) if ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'))
{ {
path[1] = ':'; path[1] = ':';
} }
} }
#endif #endif
if (name[0] && path[0]) if (name[0] && path[0])
{ {
drive = (DRIVE_DEVICE*) calloc(1, sizeof(DRIVE_DEVICE)); drive = (DRIVE_DEVICE*) calloc(1, sizeof(DRIVE_DEVICE));
if (!drive) if (!drive)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -806,9 +808,9 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
drive->device.IRPRequest = drive_irp_request; drive->device.IRPRequest = drive_irp_request;
drive->device.Free = drive_free; drive->device.Free = drive_free;
drive->rdpcontext = pEntryPoints->rdpcontext; drive->rdpcontext = pEntryPoints->rdpcontext;
length = (int) strlen(name); length = (int) strlen(name);
drive->device.data = Stream_New(NULL, length + 1); drive->device.data = Stream_New(NULL, length + 1);
if (!drive->device.data) if (!drive->device.data)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -820,17 +822,19 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
Stream_Write_UINT8(drive->device.data, name[i] < 0 ? '_' : name[i]); Stream_Write_UINT8(drive->device.data, name[i] < 0 ? '_' : name[i]);
drive->path = path; drive->path = path;
drive->files = ListDictionary_New(TRUE); drive->files = ListDictionary_New(TRUE);
if (!drive->files) if (!drive->files)
{ {
WLog_ERR(TAG, "ListDictionary_New failed!"); WLog_ERR(TAG, "ListDictionary_New failed!");
error = CHANNEL_RC_NO_MEMORY; error = CHANNEL_RC_NO_MEMORY;
goto out_error; goto out_error;
} }
ListDictionary_ValueObject(drive->files)->fnObjectFree = (OBJECT_FREE_FN) drive_file_free;
ListDictionary_ValueObject(drive->files)->fnObjectFree =
(OBJECT_FREE_FN) drive_file_free;
drive->IrpQueue = MessageQueue_New(NULL); drive->IrpQueue = MessageQueue_New(NULL);
if (!drive->IrpQueue) if (!drive->IrpQueue)
{ {
WLog_ERR(TAG, "ListDictionary_New failed!"); WLog_ERR(TAG, "ListDictionary_New failed!");
@ -838,13 +842,15 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
goto out_error; goto out_error;
} }
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) drive))) if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
(DEVICE*) drive)))
{ {
WLog_ERR(TAG, "RegisterDevice failed with error %lu!", error); WLog_ERR(TAG, "RegisterDevice failed with error %lu!", error);
goto out_error; goto out_error;
} }
if (!(drive->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, drive, CREATE_SUSPENDED, NULL))) if (!(drive->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drive_thread_func, drive, CREATE_SUSPENDED, NULL)))
{ {
WLog_ERR(TAG, "CreateThread failed!"); WLog_ERR(TAG, "CreateThread failed!");
goto out_error; goto out_error;
@ -852,6 +858,7 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
ResumeThread(drive->thread); ResumeThread(drive->thread);
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
out_error: out_error:
MessageQueue_Free(drive->IrpQueue); MessageQueue_Free(drive->IrpQueue);
@ -881,21 +888,19 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
char* dev; char* dev;
int len; int len;
char devlist[512], buf[512]; char devlist[512], buf[512];
char *bufdup; char* bufdup;
char *devdup; char* devdup;
#endif #endif
drive = (RDPDR_DRIVE*) pEntryPoints->device; drive = (RDPDR_DRIVE*) pEntryPoints->device;
#ifndef WIN32 #ifndef WIN32
sys_code_page = CP_UTF8; sys_code_page = CP_UTF8;
if (strcmp(drive->Path, "*") == 0) if (strcmp(drive->Path, "*") == 0)
{ {
/* all drives */ /* all drives */
free(drive->Path); free(drive->Path);
drive->Path = _strdup("/"); drive->Path = _strdup("/");
if (!drive->Path) if (!drive->Path)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
@ -905,15 +910,14 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
else if (strcmp(drive->Path, "%") == 0) else if (strcmp(drive->Path, "%") == 0)
{ {
char* home_env = NULL; char* home_env = NULL;
/* home directory */ /* home directory */
home_env = getenv("HOME"); home_env = getenv("HOME");
free(drive->Path); free(drive->Path);
if (home_env) if (home_env)
{ {
drive->Path = _strdup(home_env); drive->Path = _strdup(home_env);
if (!drive->Path) if (!drive->Path)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
@ -923,6 +927,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
else else
{ {
drive->Path = _strdup("/"); drive->Path = _strdup("/");
if (!drive->Path) if (!drive->Path)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
@ -932,29 +937,29 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
} }
error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path); error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
#else #else
sys_code_page = GetACP(); sys_code_page = GetACP();
/* Special case: path[0] == '*' -> export all drives */ /* Special case: path[0] == '*' -> export all drives */
/* Special case: path[0] == '%' -> user home dir */ /* Special case: path[0] == '%' -> user home dir */
if (strcmp(drive->Path, "%") == 0) if (strcmp(drive->Path, "%") == 0)
{ {
GetEnvironmentVariableA("USERPROFILE", buf, sizeof(buf)); GetEnvironmentVariableA("USERPROFILE", buf, sizeof(buf));
PathCchAddBackslashA(buf, sizeof(buf)); PathCchAddBackslashA(buf, sizeof(buf));
free(drive->Path); free(drive->Path);
drive->Path = _strdup(buf); drive->Path = _strdup(buf);
if (!drive->Path) if (!drive->Path)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path); error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
} }
else if (strcmp(drive->Path, "*") == 0) else if (strcmp(drive->Path, "*") == 0)
{ {
int i; int i;
/* Enumerate all devices: */ /* Enumerate all devices: */
GetLogicalDriveStringsA(sizeof(devlist) - 1, devlist); GetLogicalDriveStringsA(sizeof(devlist) - 1, devlist);
@ -968,11 +973,13 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
buf[len + 1] = dev[0]; buf[len + 1] = dev[0];
buf[len + 2] = 0; buf[len + 2] = 0;
buf[len + 3] = 0; buf[len + 3] = 0;
if (!(bufdup = _strdup(buf))) if (!(bufdup = _strdup(buf)))
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
if (!(devdup = _strdup(dev))) if (!(devdup = _strdup(dev)))
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
@ -990,7 +997,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
{ {
error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path); error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
} }
#endif
#endif
return error; return error;
} }

View File

@ -73,9 +73,8 @@ static UINT echo_server_open_channel(echo_server* echo)
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
echo->SessionId = (DWORD) *pSessionId; echo->SessionId = (DWORD) * pSessionId;
WTSFreeMemory(pSessionId); WTSFreeMemory(pSessionId);
hEvent = WTSVirtualChannelManagerGetEventHandle(echo->context.vcm); hEvent = WTSVirtualChannelManagerGetEventHandle(echo->context.vcm);
StartTick = GetTickCount(); StartTick = GetTickCount();
@ -95,6 +94,7 @@ static UINT echo_server_open_channel(echo_server* echo)
break; break;
Error = GetLastError(); Error = GetLastError();
if (Error == ERROR_NOT_FOUND) if (Error == ERROR_NOT_FOUND)
break; break;
@ -117,15 +117,19 @@ static void* echo_server_thread_func(void* arg)
echo_server* echo = (echo_server*) arg; echo_server* echo = (echo_server*) arg;
UINT error; UINT error;
DWORD status; DWORD status;
freerdp_channel_init_thread_context(echo->context.rdpcontext); freerdp_channel_init_thread_context(echo->context.rdpcontext);
if ((error = echo_server_open_channel(echo))) if ((error = echo_server_open_channel(echo)))
{ {
UINT error2 = 0; UINT error2 = 0;
WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error); WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error);
IFCALLRET(echo->context.OpenResult, error2, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED); IFCALLRET(echo->context.OpenResult, error2, &echo->context,
ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
if (error2) if (error2)
WLog_ERR(TAG, "echo server's OpenResult callback failed with error %lu", error2); WLog_ERR(TAG, "echo server's OpenResult callback failed with error %lu",
error2);
goto out; goto out;
} }
@ -133,7 +137,8 @@ static void* echo_server_thread_func(void* arg)
BytesReturned = 0; BytesReturned = 0;
ChannelEvent = NULL; ChannelEvent = NULL;
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualEventHandle, &buffer,
&BytesReturned) == TRUE)
{ {
if (BytesReturned == sizeof(HANDLE)) if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
@ -160,34 +165,44 @@ static void* echo_server_thread_func(void* arg)
if (status == WAIT_OBJECT_0) if (status == WAIT_OBJECT_0)
{ {
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_CLOSED); IFCALLRET(echo->context.OpenResult, error, &echo->context,
ECHO_SERVER_OPEN_RESULT_CLOSED);
if (error) if (error)
WLog_ERR(TAG, "OpenResult failed with error %lu!", error); WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
break; break;
} }
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer,
&BytesReturned) == FALSE)
{ {
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_ERROR); IFCALLRET(echo->context.OpenResult, error, &echo->context,
ECHO_SERVER_OPEN_RESULT_ERROR);
if (error) if (error)
WLog_ERR(TAG, "OpenResult failed with error %lu!", error); WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
break; break;
} }
ready = *((BOOL*) buffer); ready = *((BOOL*) buffer);
WTSFreeMemory(buffer); WTSFreeMemory(buffer);
if (ready) if (ready)
{ {
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_OK); IFCALLRET(echo->context.OpenResult, error, &echo->context,
ECHO_SERVER_OPEN_RESULT_OK);
if (error) if (error)
WLog_ERR(TAG, "OpenResult failed with error %lu!", error); WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
break; break;
} }
} }
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -211,10 +226,11 @@ static void* echo_server_thread_func(void* arg)
break; break;
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned); WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned);
if (BytesReturned < 1) if (BytesReturned < 1)
continue; continue;
if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
@ -230,19 +246,24 @@ static void* echo_server_thread_func(void* arg)
break; break;
} }
IFCALLRET(echo->context.Response, error, &echo->context, (BYTE *) Stream_Buffer(s), BytesReturned); IFCALLRET(echo->context.Response, error, &echo->context,
(BYTE*) Stream_Buffer(s), BytesReturned);
if (error) if (error)
{ {
WLog_ERR(TAG, "Response failed with error %lu!", error); WLog_ERR(TAG, "Response failed with error %lu!", error);
break; break;
} }
} }
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
WTSVirtualChannelClose(echo->echo_channel); WTSVirtualChannelClose(echo->echo_channel);
echo->echo_channel = NULL; echo->echo_channel = NULL;
out: out:
if (error && echo->context.rdpcontext) if (error && echo->context.rdpcontext)
setChannelError(echo->context.rdpcontext, error, "echo_server_thread_func reported an error"); setChannelError(echo->context.rdpcontext, error,
"echo_server_thread_func reported an error");
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
@ -265,7 +286,8 @@ static UINT echo_server_open(echo_server_context* context)
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
if (!(echo->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL))) if (!(echo->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL)))
{ {
WLog_ERR(TAG, "CreateEvent failed!"); WLog_ERR(TAG, "CreateEvent failed!");
CloseHandle(echo->stopEvent); CloseHandle(echo->stopEvent);
@ -273,6 +295,7 @@ static UINT echo_server_open(echo_server_context* context)
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -302,20 +325,20 @@ static UINT echo_server_close(echo_server_context* context)
echo->thread = NULL; echo->thread = NULL;
echo->stopEvent = NULL; echo->stopEvent = NULL;
} }
return error; return error;
} }
static BOOL echo_server_request(echo_server_context* context, const BYTE* buffer, UINT32 length) static BOOL echo_server_request(echo_server_context* context,
const BYTE* buffer, UINT32 length)
{ {
echo_server* echo = (echo_server*) context; echo_server* echo = (echo_server*) context;
return WTSVirtualChannelWrite(echo->echo_channel, (PCHAR) buffer, length, NULL); return WTSVirtualChannelWrite(echo->echo_channel, (PCHAR) buffer, length, NULL);
} }
echo_server_context* echo_server_context_new(HANDLE vcm) echo_server_context* echo_server_context_new(HANDLE vcm)
{ {
echo_server* echo; echo_server* echo;
echo = (echo_server*) calloc(1, sizeof(echo_server)); echo = (echo_server*) calloc(1, sizeof(echo_server));
if (echo) if (echo)
@ -334,8 +357,6 @@ echo_server_context* echo_server_context_new(HANDLE vcm)
void echo_server_context_free(echo_server_context* context) void echo_server_context_free(echo_server_context* context)
{ {
echo_server* echo = (echo_server*) context; echo_server* echo = (echo_server*) context;
echo_server_close(context); echo_server_close(context);
free(echo); free(echo);
} }

View File

@ -1045,7 +1045,6 @@ static void* encomsp_virtual_channel_client_thread(void* arg)
wMessage message; wMessage message;
encomspPlugin* encomsp = (encomspPlugin*) arg; encomspPlugin* encomsp = (encomspPlugin*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(encomsp->rdpcontext); freerdp_channel_init_thread_context(encomsp->rdpcontext);
encomsp_process_connect(encomsp); encomsp_process_connect(encomsp);
@ -1301,6 +1300,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
s_TLSPluginContext = encomsp; s_TLSPluginContext = encomsp;
return TRUE; return TRUE;
error_out: error_out:
if (context) if (context)
*(pEntryPointsEx->ppInterface) = NULL; *(pEntryPointsEx->ppInterface) = NULL;

View File

@ -45,7 +45,6 @@ static UINT encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */ Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */
Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */ Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -55,7 +54,6 @@ static int encomsp_write_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
{ {
Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */ Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */
Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */ Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */
return 1; return 1;
} }
@ -75,7 +73,6 @@ static int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
return -1; return -1;
Stream_Read(s, &(str->wString), (str->cchString * 2)); /* String (variable) */ Stream_Read(s, &(str->wString), (str->cchString * 2)); /* String (variable) */
return 1; return 1;
} }
@ -86,14 +83,13 @@ static int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerContext* context, wStream* s, ENCOMSP_ORDER_HEADER* header) static UINT encomsp_recv_change_participant_control_level_pdu(
EncomspServerContext* context, wStream* s, ENCOMSP_ORDER_HEADER* header)
{ {
int beg, end; int beg, end;
ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu; ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 6) if (Stream_GetRemainingLength(s) < 6)
@ -104,7 +100,6 @@ static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerConte
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
end = (int) Stream_GetPosition(s); end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end) if ((beg + header->Length) < end)
@ -125,8 +120,10 @@ static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerConte
} }
IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu); IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu);
if (error) if (error)
WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu", error); WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu",
error);
return error; return error;
} }
@ -136,7 +133,8 @@ static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerConte
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s) static UINT encomsp_server_receive_pdu(EncomspServerContext* context,
wStream* s)
{ {
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
ENCOMSP_ORDER_HEADER header; ENCOMSP_ORDER_HEADER header;
@ -149,14 +147,18 @@ static UINT encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s
return error; return error;
} }
WLog_INFO(TAG, "EncomspReceive: Type: %d Length: %d", header.Type, header.Length); WLog_INFO(TAG, "EncomspReceive: Type: %d Length: %d", header.Type,
header.Length);
switch (header.Type) switch (header.Type)
{ {
case ODTYPE_PARTICIPANT_CTRL_CHANGED: case ODTYPE_PARTICIPANT_CTRL_CHANGED:
if ((error = encomsp_recv_change_participant_control_level_pdu(context, s, &header))) if ((error = encomsp_recv_change_participant_control_level_pdu(context, s,
&header)))
{ {
WLog_ERR(TAG, "encomsp_recv_change_participant_control_level_pdu failed with error %lu!", error); WLog_ERR(TAG,
"encomsp_recv_change_participant_control_level_pdu failed with error %lu!",
error);
return error; return error;
} }
@ -184,15 +186,13 @@ static void* encomsp_server_thread(void* arg)
EncomspServerContext* context; EncomspServerContext* context;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
DWORD status; DWORD status;
context = (EncomspServerContext*) arg; context = (EncomspServerContext*) arg;
freerdp_channel_init_thread_context(context->rdpcontext); freerdp_channel_init_thread_context(context->rdpcontext);
buffer = NULL; buffer = NULL;
BytesReturned = 0; BytesReturned = 0;
ChannelEvent = NULL; ChannelEvent = NULL;
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -200,7 +200,8 @@ static void* encomsp_server_thread(void* arg)
goto out; goto out;
} }
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
&buffer, &BytesReturned) == TRUE)
{ {
if (BytesReturned == sizeof(HANDLE)) if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
@ -238,14 +239,17 @@ static void* encomsp_server_thread(void* arg)
} }
WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned); WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned);
if (BytesReturned < 1) if (BytesReturned < 1)
continue; continue;
if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
error = CHANNEL_RC_NO_MEMORY; error = CHANNEL_RC_NO_MEMORY;
break; break;
} }
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{ {
@ -262,11 +266,13 @@ static void* encomsp_server_thread(void* arg)
{ {
Stream_SealLength(s); Stream_SealLength(s);
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
if ((error = encomsp_server_receive_pdu(context, s))) if ((error = encomsp_server_receive_pdu(context, s)))
{ {
WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %lu!", error); WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %lu!", error);
break; break;
} }
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
} }
} }
@ -274,8 +280,10 @@ static void* encomsp_server_thread(void* arg)
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
out: out:
if (error && context->rdpcontext) if (error && context->rdpcontext)
setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error"); setChannelError(context->rdpcontext, error,
"encomsp_server_thread reported an error");
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
@ -288,7 +296,8 @@ out:
*/ */
static UINT encomsp_server_start(EncomspServerContext* context) static UINT encomsp_server_start(EncomspServerContext* context)
{ {
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "encomsp"); context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm,
WTS_CURRENT_SESSION, "encomsp");
if (!context->priv->ChannelHandle) if (!context->priv->ChannelHandle)
return CHANNEL_RC_BAD_CHANNEL; return CHANNEL_RC_BAD_CHANNEL;
@ -327,24 +336,21 @@ static UINT encomsp_server_stop(EncomspServerContext* context)
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
return error; return error;
} }
CloseHandle(context->priv->Thread);
CloseHandle(context->priv->Thread);
return error; return error;
} }
EncomspServerContext* encomsp_server_context_new(HANDLE vcm) EncomspServerContext* encomsp_server_context_new(HANDLE vcm)
{ {
EncomspServerContext* context; EncomspServerContext* context;
context = (EncomspServerContext*) calloc(1, sizeof(EncomspServerContext)); context = (EncomspServerContext*) calloc(1, sizeof(EncomspServerContext));
if (context) if (context)
{ {
context->vcm = vcm; context->vcm = vcm;
context->Start = encomsp_server_start; context->Start = encomsp_server_start;
context->Stop = encomsp_server_stop; context->Stop = encomsp_server_stop;
context->priv = (EncomspServerPrivate*) calloc(1, sizeof(EncomspServerPrivate)); context->priv = (EncomspServerPrivate*) calloc(1, sizeof(EncomspServerPrivate));
if (!context->priv) if (!context->priv)

View File

@ -84,12 +84,10 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
char* path = NULL; char* path = NULL;
int status; int status;
UINT32 PathLength; UINT32 PathLength;
Stream_Seek(irp->input, 28); Stream_Seek(irp->input, 28);
/* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */ /* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */
/* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */ /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */
Stream_Read_UINT32(irp->input, PathLength); Stream_Read_UINT32(irp->input, PathLength);
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input), status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
PathLength / 2, &path, 0, NULL, NULL); PathLength / 2, &path, 0, NULL, NULL);
@ -113,15 +111,12 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
/* all read and write operations should be non-blocking */ /* all read and write operations should be non-blocking */
if (fcntl(parallel->file, F_SETFL, O_NONBLOCK) == -1) if (fcntl(parallel->file, F_SETFL, O_NONBLOCK) == -1)
{ {
} }
} }
Stream_Write_UINT32(irp->output, parallel->id); Stream_Write_UINT32(irp->output, parallel->id);
Stream_Write_UINT8(irp->output, 0); Stream_Write_UINT8(irp->output, 0);
free(path); free(path);
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -134,15 +129,12 @@ static UINT parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
{ {
if (close(parallel->file) < 0) if (close(parallel->file) < 0)
{ {
} }
else else
{ {
} }
Stream_Zero(irp->output, 5); /* Padding(5) */ Stream_Zero(irp->output, 5); /* Padding(5) */
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -157,11 +149,10 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
UINT64 Offset; UINT64 Offset;
ssize_t status; ssize_t status;
BYTE* buffer = NULL; BYTE* buffer = NULL;
Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset); Stream_Read_UINT64(irp->input, Offset);
buffer = (BYTE*) malloc(Length); buffer = (BYTE*) malloc(Length);
if (!buffer) if (!buffer)
{ {
WLog_ERR(TAG, "malloc failed!"); WLog_ERR(TAG, "malloc failed!");
@ -179,7 +170,6 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
} }
else else
{ {
} }
Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT32(irp->output, Length);
@ -192,11 +182,11 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
free(buffer); free(buffer);
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Write(irp->output, buffer, Length); Stream_Write(irp->output, buffer, Length);
} }
free(buffer); free(buffer);
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -211,11 +201,9 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
UINT32 Length; UINT32 Length;
UINT64 Offset; UINT64 Offset;
ssize_t status; ssize_t status;
Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset); Stream_Read_UINT64(irp->input, Offset);
Stream_Seek(irp->input, 20); /* Padding */ Stream_Seek(irp->input, 20); /* Padding */
len = Length; len = Length;
while (len > 0) while (len > 0)
@ -235,7 +223,6 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT32(irp->output, Length);
Stream_Write_UINT8(irp->output, 0); /* Padding */ Stream_Write_UINT8(irp->output, 0); /* Padding */
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -244,7 +231,8 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp) static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel,
IRP* irp)
{ {
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */ Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */
return irp->Complete(irp); return irp->Complete(irp);
@ -267,6 +255,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
WLog_ERR(TAG, "parallel_process_irp_create failed with error %d!", error); WLog_ERR(TAG, "parallel_process_irp_create failed with error %d!", error);
return error; return error;
} }
break; break;
case IRP_MJ_CLOSE: case IRP_MJ_CLOSE:
@ -275,6 +264,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
WLog_ERR(TAG, "parallel_process_irp_close failed with error %d!", error); WLog_ERR(TAG, "parallel_process_irp_close failed with error %d!", error);
return error; return error;
} }
break; break;
case IRP_MJ_READ: case IRP_MJ_READ:
@ -283,6 +273,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
WLog_ERR(TAG, "parallel_process_irp_read failed with error %d!", error); WLog_ERR(TAG, "parallel_process_irp_read failed with error %d!", error);
return error; return error;
} }
break; break;
case IRP_MJ_WRITE: case IRP_MJ_WRITE:
@ -291,14 +282,17 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
WLog_ERR(TAG, "parallel_process_irp_write failed with error %d!", error); WLog_ERR(TAG, "parallel_process_irp_write failed with error %d!", error);
return error; return error;
} }
break; break;
case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_DEVICE_CONTROL:
if ((error = parallel_process_irp_device_control(parallel, irp))) if ((error = parallel_process_irp_device_control(parallel, irp)))
{ {
WLog_ERR(TAG, "parallel_process_irp_device_control failed with error %d!", error); WLog_ERR(TAG, "parallel_process_irp_device_control failed with error %d!",
error);
return error; return error;
} }
break; break;
default: default:
@ -306,6 +300,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
return irp->Complete(irp); return irp->Complete(irp);
break; break;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -315,8 +310,8 @@ static void* parallel_thread_func(void* arg)
wMessage message; wMessage message;
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) arg; PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(parallel->rdpcontext); freerdp_channel_init_thread_context(parallel->rdpcontext);
while (1) while (1)
{ {
if (!MessageQueue_Wait(parallel->queue)) if (!MessageQueue_Wait(parallel->queue))
@ -344,8 +339,10 @@ static void* parallel_thread_func(void* arg)
break; break;
} }
} }
if (error && parallel->rdpcontext) if (error && parallel->rdpcontext)
setChannelError(parallel->rdpcontext, error, "parallel_thread_func reported an error"); setChannelError(parallel->rdpcontext, error,
"parallel_thread_func reported an error");
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
@ -365,6 +362,7 @@ static UINT parallel_irp_request(DEVICE* device, IRP* irp)
WLog_ERR(TAG, "MessageQueue_Post failed!"); WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -378,17 +376,17 @@ static UINT parallel_free(DEVICE* device)
UINT error; UINT error;
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device;
if (MessageQueue_PostQuit(parallel->queue, 0) && (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED)) if (MessageQueue_PostQuit(parallel->queue, 0)
&& (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED))
{ {
error = GetLastError(); error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error; return error;
} }
CloseHandle(parallel->thread);
CloseHandle(parallel->thread);
Stream_Free(parallel->device.data, TRUE); Stream_Free(parallel->device.data, TRUE);
MessageQueue_Free(parallel->queue); MessageQueue_Free(parallel->queue);
free(parallel); free(parallel);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -413,7 +411,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
RDPDR_PARALLEL* device; RDPDR_PARALLEL* device;
PARALLEL_DEVICE* parallel; PARALLEL_DEVICE* parallel;
UINT error; UINT error;
device = (RDPDR_PARALLEL*) pEntryPoints->device; device = (RDPDR_PARALLEL*) pEntryPoints->device;
name = device->Name; name = device->Name;
path = device->Path; path = device->Path;
@ -427,6 +424,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
if (name[0] && path[0]) if (name[0] && path[0])
{ {
parallel = (PARALLEL_DEVICE*) calloc(1, sizeof(PARALLEL_DEVICE)); parallel = (PARALLEL_DEVICE*) calloc(1, sizeof(PARALLEL_DEVICE));
if (!parallel) if (!parallel)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -438,9 +436,9 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
parallel->device.IRPRequest = parallel_irp_request; parallel->device.IRPRequest = parallel_irp_request;
parallel->device.Free = parallel_free; parallel->device.Free = parallel_free;
parallel->rdpcontext = pEntryPoints->rdpcontext; parallel->rdpcontext = pEntryPoints->rdpcontext;
length = strlen(name); length = strlen(name);
parallel->device.data = Stream_New(NULL, length + 1); parallel->device.data = Stream_New(NULL, length + 1);
if (!parallel->device.data) if (!parallel->device.data)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -452,8 +450,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
Stream_Write_UINT8(parallel->device.data, name[i] < 0 ? '_' : name[i]); Stream_Write_UINT8(parallel->device.data, name[i] < 0 ? '_' : name[i]);
parallel->path = path; parallel->path = path;
parallel->queue = MessageQueue_New(NULL); parallel->queue = MessageQueue_New(NULL);
if (!parallel->queue) if (!parallel->queue)
{ {
WLog_ERR(TAG, "MessageQueue_New failed!"); WLog_ERR(TAG, "MessageQueue_New failed!");
@ -461,14 +459,15 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
goto error_out; goto error_out;
} }
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) parallel))) if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
(DEVICE*) parallel)))
{ {
WLog_ERR(TAG, "RegisterDevice failed with error %lu!", error); WLog_ERR(TAG, "RegisterDevice failed with error %lu!", error);
goto error_out; goto error_out;
} }
if (!(parallel->thread = CreateThread(NULL, 0,
if (!(parallel->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) parallel_thread_func, (void*) parallel, 0, NULL))) (LPTHREAD_START_ROUTINE) parallel_thread_func, (void*) parallel, 0, NULL)))
{ {
WLog_ERR(TAG, "CreateThread failed!"); WLog_ERR(TAG, "CreateThread failed!");
error = ERROR_INTERNAL_ERROR; error = ERROR_INTERNAL_ERROR;

View File

@ -586,8 +586,8 @@ static void* rail_virtual_channel_client_thread(void* arg)
wMessage message; wMessage message;
railPlugin* rail = (railPlugin*) arg; railPlugin* rail = (railPlugin*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(rail->rdpcontext); freerdp_channel_init_thread_context(rail->rdpcontext);
while (1) while (1)
{ {
if (!MessageQueue_Wait(rail->queue)) if (!MessageQueue_Wait(rail->queue))

View File

@ -864,8 +864,8 @@ static void* drive_hotplug_thread_func(void* arg)
UINT error = 0; UINT error = 0;
DWORD status; DWORD status;
rdpdr = (rdpdrPlugin*) arg; rdpdr = (rdpdrPlugin*) arg;
freerdp_channel_init_thread_context(rdpdr->rdpcontext); freerdp_channel_init_thread_context(rdpdr->rdpcontext);
if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{ {
WLog_ERR(TAG, "CreateEvent failed!"); WLog_ERR(TAG, "CreateEvent failed!");
@ -1565,6 +1565,7 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
freerdp_channel_init_thread_context(rdpdr->rdpcontext); freerdp_channel_init_thread_context(rdpdr->rdpcontext);
s_TLSPluginContext = rdpdr; s_TLSPluginContext = rdpdr;
if ((error = rdpdr_process_connect(rdpdr))) if ((error = rdpdr_process_connect(rdpdr)))
{ {
WLog_ERR(TAG, "rdpdr_process_connect failed with error %lu!", error); WLog_ERR(TAG, "rdpdr_process_connect failed with error %lu!", error);

File diff suppressed because it is too large Load Diff

View File

@ -138,16 +138,16 @@ UINT rdpei_add_frame(RdpeiClientContext* context)
int i; int i;
RDPINPUT_CONTACT_DATA* contact; RDPINPUT_CONTACT_DATA* contact;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
rdpei->frame.contactCount = 0; rdpei->frame.contactCount = 0;
for (i = 0; i < rdpei->maxTouchContacts; i++) for (i = 0; i < rdpei->maxTouchContacts; i++)
{ {
contact = (RDPINPUT_CONTACT_DATA*) &(rdpei->contactPoints[i].data); contact = (RDPINPUT_CONTACT_DATA*) & (rdpei->contactPoints[i].data);
if (rdpei->contactPoints[i].dirty) if (rdpei->contactPoints[i].dirty)
{ {
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, sizeof(RDPINPUT_CONTACT_DATA)); CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact,
sizeof(RDPINPUT_CONTACT_DATA));
rdpei->contactPoints[i].dirty = FALSE; rdpei->contactPoints[i].dirty = FALSE;
rdpei->frame.contactCount++; rdpei->frame.contactCount++;
} }
@ -160,7 +160,8 @@ UINT rdpei_add_frame(RdpeiClientContext* context)
contact->contactFlags |= CONTACT_FLAG_INCONTACT; contact->contactFlags |= CONTACT_FLAG_INCONTACT;
} }
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, sizeof(RDPINPUT_CONTACT_DATA)); CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact,
sizeof(RDPINPUT_CONTACT_DATA));
rdpei->frame.contactCount++; rdpei->frame.contactCount++;
} }
} }
@ -175,15 +176,14 @@ static void* rdpei_schedule_thread(void* arg)
RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface; RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface;
HANDLE hdl[] = {rdpei->event, rdpei->stopEvent}; HANDLE hdl[] = {rdpei->event, rdpei->stopEvent};
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(rdpei->rdpcontext); freerdp_channel_init_thread_context(rdpei->rdpcontext);
if (!rdpei) if (!rdpei)
{ {
error = ERROR_INVALID_PARAMETER; error = ERROR_INVALID_PARAMETER;
goto out; goto out;
} }
if (!context) if (!context)
{ {
error = ERROR_INVALID_PARAMETER; error = ERROR_INVALID_PARAMETER;
@ -228,11 +228,12 @@ static void* rdpei_schedule_thread(void* arg)
} }
out: out:
if (error && rdpei->rdpcontext) if (error && rdpei->rdpcontext)
setChannelError(rdpei->rdpcontext, error, "rdpei_schedule_thread reported an error"); setChannelError(rdpei->rdpcontext, error,
"rdpei_schedule_thread reported an error");
ExitThread(0); ExitThread(0);
return NULL; return NULL;
} }
@ -241,22 +242,20 @@ out:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId, UINT32 pduLength) UINT rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s,
UINT16 eventId, UINT32 pduLength)
{ {
UINT status; UINT status;
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
Stream_Write_UINT16(s, eventId); /* eventId (2 bytes) */ Stream_Write_UINT16(s, eventId); /* eventId (2 bytes) */
Stream_Write_UINT32(s, pduLength); /* pduLength (4 bytes) */ Stream_Write_UINT32(s, pduLength); /* pduLength (4 bytes) */
Stream_SetPosition(s, Stream_Length(s)); Stream_SetPosition(s, Stream_Length(s));
status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s),
status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); Stream_Buffer(s), NULL);
#ifdef WITH_DEBUG_RDPEI #ifdef WITH_DEBUG_RDPEI
WLog_DBG(TAG, "rdpei_send_pdu: eventId: %d (%s) length: %d status: %d", WLog_DBG(TAG, "rdpei_send_pdu: eventId: %d (%s) length: %d status: %d",
eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength, status); eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength, status);
#endif #endif
return status; return status;
} }
@ -272,29 +271,26 @@ UINT rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
UINT32 flags; UINT32 flags;
UINT32 pduLength; UINT32 pduLength;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) callback->plugin; RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) callback->plugin;
flags = 0; flags = 0;
flags |= READY_FLAGS_SHOW_TOUCH_VISUALS; flags |= READY_FLAGS_SHOW_TOUCH_VISUALS;
//flags |= READY_FLAGS_DISABLE_TIMESTAMP_INJECTION; //flags |= READY_FLAGS_DISABLE_TIMESTAMP_INJECTION;
pduLength = RDPINPUT_HEADER_LENGTH + 10; pduLength = RDPINPUT_HEADER_LENGTH + 10;
s = Stream_New(NULL, pduLength); s = Stream_New(NULL, pduLength);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
Stream_Write_UINT32(s, flags); /* flags (4 bytes) */ Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V10); /* protocolVersion (4 bytes) */ Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V10); /* protocolVersion (4 bytes) */
Stream_Write_UINT16(s, rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */ Stream_Write_UINT16(s,
rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */
Stream_SealLength(s); Stream_SealLength(s);
status = rdpei_send_pdu(callback, s, EVENTID_CS_READY, pduLength); status = rdpei_send_pdu(callback, s, EVENTID_CS_READY, pduLength);
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
return status; return status;
} }
@ -329,19 +325,18 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
UINT32 index; UINT32 index;
int rectSize = 2; int rectSize = 2;
RDPINPUT_CONTACT_DATA* contact; RDPINPUT_CONTACT_DATA* contact;
#ifdef WITH_DEBUG_RDPEI #ifdef WITH_DEBUG_RDPEI
WLog_DBG(TAG, "contactCount: %d", frame->contactCount); WLog_DBG(TAG, "contactCount: %d", frame->contactCount);
WLog_DBG(TAG, "frameOffset: 0x%08X", (UINT32) frame->frameOffset); WLog_DBG(TAG, "frameOffset: 0x%08X", (UINT32) frame->frameOffset);
#endif #endif
rdpei_write_2byte_unsigned(s,
rdpei_write_2byte_unsigned(s, frame->contactCount); /* contactCount (TWO_BYTE_UNSIGNED_INTEGER) */ frame->contactCount); /* contactCount (TWO_BYTE_UNSIGNED_INTEGER) */
/** /**
* the time offset from the previous frame (in microseconds). * the time offset from the previous frame (in microseconds).
* If this is the first frame being transmitted then this field MUST be set to zero. * If this is the first frame being transmitted then this field MUST be set to zero.
*/ */
rdpei_write_8byte_unsigned(s, frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */ rdpei_write_8byte_unsigned(s,
frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */
if (!Stream_EnsureRemainingCapacity(s, (size_t) frame->contactCount * 64)) if (!Stream_EnsureRemainingCapacity(s, (size_t) frame->contactCount * 64))
{ {
@ -352,13 +347,11 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
for (index = 0; index < frame->contactCount; index++) for (index = 0; index < frame->contactCount; index++)
{ {
contact = &frame->contacts[index]; contact = &frame->contacts[index];
contact->fieldsPresent |= CONTACT_DATA_CONTACTRECT_PRESENT; contact->fieldsPresent |= CONTACT_DATA_CONTACTRECT_PRESENT;
contact->contactRectLeft = contact->x - rectSize; contact->contactRectLeft = contact->x - rectSize;
contact->contactRectTop = contact->y - rectSize; contact->contactRectTop = contact->y - rectSize;
contact->contactRectRight = contact->x + rectSize; contact->contactRectRight = contact->x + rectSize;
contact->contactRectBottom = contact->y + rectSize; contact->contactRectBottom = contact->y + rectSize;
#ifdef WITH_DEBUG_RDPEI #ifdef WITH_DEBUG_RDPEI
WLog_DBG(TAG, "contact[%d].contactId: %d", index, contact->contactId); WLog_DBG(TAG, "contact[%d].contactId: %d", index, contact->contactId);
WLog_DBG(TAG, "contact[%d].fieldsPresent: %d", index, contact->fieldsPresent); WLog_DBG(TAG, "contact[%d].fieldsPresent: %d", index, contact->fieldsPresent);
@ -367,15 +360,11 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
WLog_DBG(TAG, "contact[%d].contactFlags: 0x%04X", index, contact->contactFlags); WLog_DBG(TAG, "contact[%d].contactFlags: 0x%04X", index, contact->contactFlags);
rdpei_print_contact_flags(contact->contactFlags); rdpei_print_contact_flags(contact->contactFlags);
#endif #endif
Stream_Write_UINT8(s, contact->contactId); /* contactId (1 byte) */ Stream_Write_UINT8(s, contact->contactId); /* contactId (1 byte) */
/* fieldsPresent (TWO_BYTE_UNSIGNED_INTEGER) */ /* fieldsPresent (TWO_BYTE_UNSIGNED_INTEGER) */
rdpei_write_2byte_unsigned(s, contact->fieldsPresent); rdpei_write_2byte_unsigned(s, contact->fieldsPresent);
rdpei_write_4byte_signed(s, contact->x); /* x (FOUR_BYTE_SIGNED_INTEGER) */ rdpei_write_4byte_signed(s, contact->x); /* x (FOUR_BYTE_SIGNED_INTEGER) */
rdpei_write_4byte_signed(s, contact->y); /* y (FOUR_BYTE_SIGNED_INTEGER) */ rdpei_write_4byte_signed(s, contact->y); /* y (FOUR_BYTE_SIGNED_INTEGER) */
/* contactFlags (FOUR_BYTE_UNSIGNED_INTEGER) */ /* contactFlags (FOUR_BYTE_UNSIGNED_INTEGER) */
rdpei_write_4byte_unsigned(s, contact->contactFlags); rdpei_write_4byte_unsigned(s, contact->contactFlags);
@ -412,28 +401,28 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_FRAME* frame) UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback,
RDPINPUT_TOUCH_FRAME* frame)
{ {
UINT status; UINT status;
wStream* s; wStream* s;
UINT32 pduLength; UINT32 pduLength;
pduLength = 64 + (frame->contactCount * 64); pduLength = 64 + (frame->contactCount * 64);
s = Stream_New(NULL, pduLength); s = Stream_New(NULL, pduLength);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
/** /**
* the time that has elapsed (in milliseconds) from when the oldest touch frame * the time that has elapsed (in milliseconds) from when the oldest touch frame
* was generated to when it was encoded for transmission by the client. * was generated to when it was encoded for transmission by the client.
*/ */
rdpei_write_4byte_unsigned(s, (UINT32) frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */ rdpei_write_4byte_unsigned(s,
(UINT32) frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */
rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */ rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */
if ((status = rdpei_write_touch_frame(s, frame))) if ((status = rdpei_write_touch_frame(s, frame)))
@ -445,10 +434,8 @@ UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH
Stream_SealLength(s); Stream_SealLength(s);
pduLength = Stream_Length(s); pduLength = Stream_Length(s);
status = rdpei_send_pdu(callback, s, EVENTID_TOUCH, pduLength); status = rdpei_send_pdu(callback, s, EVENTID_TOUCH, pduLength);
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
return status; return status;
} }
@ -460,17 +447,16 @@ UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH
UINT rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) UINT rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
{ {
UINT32 protocolVersion; UINT32 protocolVersion;
Stream_Read_UINT32(s, protocolVersion); /* protocolVersion (4 bytes) */ Stream_Read_UINT32(s, protocolVersion); /* protocolVersion (4 bytes) */
#if 0 #if 0
if (protocolVersion != RDPINPUT_PROTOCOL_V10) if (protocolVersion != RDPINPUT_PROTOCOL_V10)
{ {
WLog_ERR(TAG, "Unknown [MS-RDPEI] protocolVersion: 0x%08X", protocolVersion); WLog_ERR(TAG, "Unknown [MS-RDPEI] protocolVersion: 0x%08X", protocolVersion);
return -1; return -1;
} }
#endif
#endif
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -483,8 +469,8 @@ UINT rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
{ {
RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface; RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
IFCALLRET(rdpei->SuspendTouch, error, rdpei); IFCALLRET(rdpei->SuspendTouch, error, rdpei);
if (error) if (error)
WLog_ERR(TAG, "rdpei->SuspendTouch failed with error %lu!", error); WLog_ERR(TAG, "rdpei->SuspendTouch failed with error %lu!", error);
@ -500,8 +486,8 @@ UINT rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
{ {
RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface; RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
IFCALLRET(rdpei->ResumeTouch, error, rdpei); IFCALLRET(rdpei->ResumeTouch, error, rdpei);
if (error) if (error)
WLog_ERR(TAG, "rdpei->ResumeTouch failed with error %lu!", error); WLog_ERR(TAG, "rdpei->ResumeTouch failed with error %lu!", error);
@ -518,10 +504,8 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
UINT16 eventId; UINT16 eventId;
UINT32 pduLength; UINT32 pduLength;
UINT error; UINT error;
Stream_Read_UINT16(s, eventId); /* eventId (2 bytes) */ Stream_Read_UINT16(s, eventId); /* eventId (2 bytes) */
Stream_Read_UINT32(s, pduLength); /* pduLength (4 bytes) */ Stream_Read_UINT32(s, pduLength); /* pduLength (4 bytes) */
#ifdef WITH_DEBUG_RDPEI #ifdef WITH_DEBUG_RDPEI
WLog_DBG(TAG, "rdpei_recv_pdu: eventId: %d (%s) length: %d", WLog_DBG(TAG, "rdpei_recv_pdu: eventId: %d (%s) length: %d",
eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength); eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength);
@ -535,11 +519,13 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
WLog_ERR(TAG, "rdpei_recv_sc_ready_pdu failed with error %lu!", error); WLog_ERR(TAG, "rdpei_recv_sc_ready_pdu failed with error %lu!", error);
return error; return error;
} }
if ((error = rdpei_send_cs_ready_pdu(callback))) if ((error = rdpei_send_cs_ready_pdu(callback)))
{ {
WLog_ERR(TAG, "rdpei_send_cs_ready_pdu failed with error %lu!", error); WLog_ERR(TAG, "rdpei_send_cs_ready_pdu failed with error %lu!", error);
return error; return error;
} }
break; break;
case EVENTID_SUSPEND_TOUCH: case EVENTID_SUSPEND_TOUCH:
@ -548,6 +534,7 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
WLog_ERR(TAG, "rdpei_recv_suspend_touch_pdu failed with error %lu!", error); WLog_ERR(TAG, "rdpei_recv_suspend_touch_pdu failed with error %lu!", error);
return error; return error;
} }
break; break;
case EVENTID_RESUME_TOUCH: case EVENTID_RESUME_TOUCH:
@ -556,6 +543,7 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
WLog_ERR(TAG, "rdpei_recv_resume_touch_pdu failed with error %lu!", error); WLog_ERR(TAG, "rdpei_recv_resume_touch_pdu failed with error %lu!", error);
return error; return error;
} }
break; break;
default: default:
@ -570,10 +558,10 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
wStream* data)
{ {
RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback; RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback;
return rdpei_recv_pdu(callback, data); return rdpei_recv_pdu(callback, data);
} }
@ -585,9 +573,7 @@ static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
static UINT rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback) static UINT rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{ {
RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback; RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback;
free(callback); free(callback);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -596,17 +582,19 @@ static UINT rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, static UINT rdpei_on_new_channel_connection(IWTSListenerCallback*
pListenerCallback,
IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept,
IWTSVirtualChannelCallback** ppCallback) IWTSVirtualChannelCallback** ppCallback)
{ {
RDPEI_CHANNEL_CALLBACK* callback; RDPEI_CHANNEL_CALLBACK* callback;
RDPEI_LISTENER_CALLBACK* listener_callback = (RDPEI_LISTENER_CALLBACK*) pListenerCallback; RDPEI_LISTENER_CALLBACK* listener_callback = (RDPEI_LISTENER_CALLBACK*)
pListenerCallback;
callback = (RDPEI_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPEI_CHANNEL_CALLBACK)); callback = (RDPEI_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPEI_CHANNEL_CALLBACK));
if (!callback) if (!callback)
{ {
WLog_ERR(TAG,"calloc failed!"); WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
@ -616,9 +604,7 @@ static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
callback->channel_mgr = listener_callback->channel_mgr; callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel; callback->channel = pChannel;
listener_callback->channel_callback = callback; listener_callback->channel_callback = callback;
*ppCallback = (IWTSVirtualChannelCallback*) callback; *ppCallback = (IWTSVirtualChannelCallback*) callback;
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -627,19 +613,22 @@ static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin,
IWTSVirtualChannelManager* pChannelMgr)
{ {
UINT error; UINT error;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin; RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin;
rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*) calloc(1 ,
sizeof(RDPEI_LISTENER_CALLBACK));
rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*) calloc(1 ,sizeof(RDPEI_LISTENER_CALLBACK));
if (!rdpei->listener_callback) if (!rdpei->listener_callback)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
rdpei->listener_callback->iface.OnNewChannelConnection = rdpei_on_new_channel_connection; rdpei->listener_callback->iface.OnNewChannelConnection =
rdpei_on_new_channel_connection;
rdpei->listener_callback->plugin = pPlugin; rdpei->listener_callback->plugin = pPlugin;
rdpei->listener_callback->channel_mgr = pChannelMgr; rdpei->listener_callback->channel_mgr = pChannelMgr;
@ -651,20 +640,18 @@ static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
} }
rdpei->listener->pInterface = rdpei->iface.pInterface; rdpei->listener->pInterface = rdpei->iface.pInterface;
InitializeCriticalSection(&rdpei->lock); InitializeCriticalSection(&rdpei->lock);
if (!(rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL))) if (!(rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
{ {
WLog_ERR(TAG, "CreateEvent failed!"); WLog_ERR(TAG, "CreateEvent failed!");
goto error_out; goto error_out;
} }
if (!(rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) if (!(rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{ {
WLog_ERR(TAG, "CreateEvent failed!"); WLog_ERR(TAG, "CreateEvent failed!");
goto error_out; goto error_out;
} }
if (!(rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) if (!(rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
@ -672,7 +659,6 @@ static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
{ {
WLog_ERR(TAG, "CreateThread failed!"); WLog_ERR(TAG, "CreateThread failed!");
goto error_out; goto error_out;
} }
return error; return error;
@ -709,13 +695,10 @@ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin)
CloseHandle(rdpei->stopEvent); CloseHandle(rdpei->stopEvent);
CloseHandle(rdpei->event); CloseHandle(rdpei->event);
CloseHandle(rdpei->thread); CloseHandle(rdpei->thread);
DeleteCriticalSection(&rdpei->lock); DeleteCriticalSection(&rdpei->lock);
free(rdpei->listener_callback); free(rdpei->listener_callback);
free(rdpei->context); free(rdpei->context);
free(rdpei); free(rdpei);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -740,7 +723,6 @@ UINT rdpei_send_frame(RdpeiClientContext* context)
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
RDPEI_CHANNEL_CALLBACK* callback = rdpei->listener_callback->channel_callback; RDPEI_CHANNEL_CALLBACK* callback = rdpei->listener_callback->channel_callback;
UINT error; UINT error;
currentTime = GetTickCount64(); currentTime = GetTickCount64();
if (!rdpei->previousFrameTime && !rdpei->currentFrameTime) if (!rdpei->previousFrameTime && !rdpei->currentFrameTime)
@ -759,9 +741,9 @@ UINT rdpei_send_frame(RdpeiClientContext* context)
WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %lu!", error); WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %lu!", error);
return error; return error;
} }
rdpei->previousFrameTime = rdpei->currentFrameTime; rdpei->previousFrameTime = rdpei->currentFrameTime;
rdpei->frame.contactCount = 0; rdpei->frame.contactCount = 0;
return error; return error;
} }
@ -770,21 +752,18 @@ UINT rdpei_send_frame(RdpeiClientContext* context)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact) UINT rdpei_add_contact(RdpeiClientContext* context,
RDPINPUT_CONTACT_DATA* contact)
{ {
RDPINPUT_CONTACT_POINT* contactPoint; RDPINPUT_CONTACT_POINT* contactPoint;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
EnterCriticalSection(&rdpei->lock); EnterCriticalSection(&rdpei->lock);
contactPoint = (RDPINPUT_CONTACT_POINT*)
contactPoint = (RDPINPUT_CONTACT_POINT*) &rdpei->contactPoints[contact->contactId]; &rdpei->contactPoints[contact->contactId];
CopyMemory(&(contactPoint->data), contact, sizeof(RDPINPUT_CONTACT_DATA)); CopyMemory(&(contactPoint->data), contact, sizeof(RDPINPUT_CONTACT_DATA));
contactPoint->dirty = TRUE; contactPoint->dirty = TRUE;
SetEvent(rdpei->event); SetEvent(rdpei->event);
LeaveCriticalSection(&rdpei->lock); LeaveCriticalSection(&rdpei->lock);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -793,7 +772,8 @@ UINT rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* conta
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y, int* contactId) UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x,
int y, int* contactId)
{ {
unsigned int i; unsigned int i;
int contactIdlocal = -1; int contactIdlocal = -1;
@ -822,20 +802,17 @@ UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y
if (contactIdlocal >= 0) if (contactIdlocal >= 0)
{ {
ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA)); ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA));
contactPoint->lastX = x; contactPoint->lastX = x;
contactPoint->lastY = y; contactPoint->lastY = y;
contact.x = x; contact.x = x;
contact.y = y; contact.y = y;
contact.contactId = (UINT32) contactIdlocal; contact.contactId = (UINT32) contactIdlocal;
contact.contactFlags |= CONTACT_FLAG_DOWN; contact.contactFlags |= CONTACT_FLAG_DOWN;
contact.contactFlags |= CONTACT_FLAG_INRANGE; contact.contactFlags |= CONTACT_FLAG_INRANGE;
contact.contactFlags |= CONTACT_FLAG_INCONTACT; contact.contactFlags |= CONTACT_FLAG_INCONTACT;
error = context->AddContact(context, &contact); error = context->AddContact(context, &contact);
} }
*contactId = contactIdlocal; *contactId = contactIdlocal;
return error; return error;
} }
@ -845,7 +822,8 @@ UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int y, int* contactId) UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x,
int y, int* contactId)
{ {
unsigned int i; unsigned int i;
int contactIdlocal = -1; int contactIdlocal = -1;
@ -871,23 +849,18 @@ UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int
if (contactIdlocal >= 0) if (contactIdlocal >= 0)
{ {
ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA)); ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA));
contactPoint->lastX = x; contactPoint->lastX = x;
contactPoint->lastY = y; contactPoint->lastY = y;
contact.x = x; contact.x = x;
contact.y = y; contact.y = y;
contact.contactId = (UINT32) contactIdlocal; contact.contactId = (UINT32) contactIdlocal;
contact.contactFlags |= CONTACT_FLAG_UPDATE; contact.contactFlags |= CONTACT_FLAG_UPDATE;
contact.contactFlags |= CONTACT_FLAG_INRANGE; contact.contactFlags |= CONTACT_FLAG_INRANGE;
contact.contactFlags |= CONTACT_FLAG_INCONTACT; contact.contactFlags |= CONTACT_FLAG_INCONTACT;
error = context->AddContact(context, &contact); error = context->AddContact(context, &contact);
} }
*contactId = contactIdlocal; *contactId = contactIdlocal;
return error; return error;
} }
@ -896,7 +869,8 @@ UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, int* contactId) UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y,
int* contactId)
{ {
unsigned int i; unsigned int i;
int contactIdlocal = -1; int contactIdlocal = -1;
@ -936,7 +910,6 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y,
contact.x = x; contact.x = x;
contact.y = y; contact.y = y;
contact.contactId = (UINT32) contactIdlocal; contact.contactId = (UINT32) contactIdlocal;
contact.contactFlags |= CONTACT_FLAG_UP; contact.contactFlags |= CONTACT_FLAG_UP;
if ((error = context->AddContact(context, &contact))) if ((error = context->AddContact(context, &contact)))
@ -951,8 +924,8 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y,
contactPoint->contactId = 0; contactPoint->contactId = 0;
contactPoint->state = RDPINPUT_CONTACT_STATE_OUT_OF_RANGE; contactPoint->state = RDPINPUT_CONTACT_STATE_OUT_OF_RANGE;
} }
*contactId = contactIdlocal;
*contactId = contactIdlocal;
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -972,15 +945,14 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
UINT error; UINT error;
RDPEI_PLUGIN* rdpei = NULL; RDPEI_PLUGIN* rdpei = NULL;
RdpeiClientContext* context = NULL; RdpeiClientContext* context = NULL;
rdpei = (RDPEI_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpei"); rdpei = (RDPEI_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpei");
if (!rdpei) if (!rdpei)
{ {
size_t size; size_t size;
rdpei = (RDPEI_PLUGIN*) calloc(1, sizeof(RDPEI_PLUGIN)); rdpei = (RDPEI_PLUGIN*) calloc(1, sizeof(RDPEI_PLUGIN));
if(!rdpei)
if (!rdpei)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
@ -990,18 +962,15 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
rdpei->iface.Connected = NULL; rdpei->iface.Connected = NULL;
rdpei->iface.Disconnected = NULL; rdpei->iface.Disconnected = NULL;
rdpei->iface.Terminated = rdpei_plugin_terminated; rdpei->iface.Terminated = rdpei_plugin_terminated;
rdpei->version = 1; rdpei->version = 1;
rdpei->currentFrameTime = 0; rdpei->currentFrameTime = 0;
rdpei->previousFrameTime = 0; rdpei->previousFrameTime = 0;
rdpei->frame.contacts = (RDPINPUT_CONTACT_DATA*) rdpei->contacts; rdpei->frame.contacts = (RDPINPUT_CONTACT_DATA*) rdpei->contacts;
rdpei->maxTouchContacts = 10; rdpei->maxTouchContacts = 10;
size = rdpei->maxTouchContacts * sizeof(RDPINPUT_CONTACT_POINT); size = rdpei->maxTouchContacts * sizeof(RDPINPUT_CONTACT_POINT);
rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*) calloc(1, size); rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*) calloc(1, size);
rdpei->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(
rdpei->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context; pEntryPoints))->instance)->context;
if (!rdpei->contactPoints) if (!rdpei->contactPoints)
{ {
@ -1011,6 +980,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
} }
context = (RdpeiClientContext*) calloc(1, sizeof(RdpeiClientContext)); context = (RdpeiClientContext*) calloc(1, sizeof(RdpeiClientContext));
if (!context) if (!context)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -1021,14 +991,13 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
context->handle = (void*) rdpei; context->handle = (void*) rdpei;
context->GetVersion = rdpei_get_version; context->GetVersion = rdpei_get_version;
context->AddContact = rdpei_add_contact; context->AddContact = rdpei_add_contact;
context->TouchBegin = rdpei_touch_begin; context->TouchBegin = rdpei_touch_begin;
context->TouchUpdate = rdpei_touch_update; context->TouchUpdate = rdpei_touch_update;
context->TouchEnd = rdpei_touch_end; context->TouchEnd = rdpei_touch_end;
rdpei->iface.pInterface = (void*) context; rdpei->iface.pInterface = (void*) context;
if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", (IWTSPlugin*) rdpei))) if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei",
(IWTSPlugin*) rdpei)))
{ {
WLog_ERR(TAG, "EntryPoints->RegisterPlugin failed with error %lu!", error); WLog_ERR(TAG, "EntryPoints->RegisterPlugin failed with error %lu!", error);
error = CHANNEL_RC_NO_MEMORY; error = CHANNEL_RC_NO_MEMORY;

View File

@ -73,7 +73,8 @@ static INLINE UINT rdpgfx_server_packet_init_header(wStream* s,
* @param s stream * @param s stream
* @param start saved start pos of the packet in the stream * @param start saved start pos of the packet in the stream
*/ */
static INLINE void rdpgfx_server_packet_complete_header(wStream* s, size_t start) static INLINE void rdpgfx_server_packet_complete_header(wStream* s,
size_t start)
{ {
size_t current = Stream_GetPosition(s); size_t current = Stream_GetPosition(s);
/* Fill actual length */ /* Fill actual length */
@ -101,7 +102,7 @@ static UINT rdpgfx_server_packet_send(RdpgfxServerContext* context, wStream* s)
* descriptor (1 bytes) + segmentCount (2 bytes) + uncompressedSize (4 bytes) * descriptor (1 bytes) + segmentCount (2 bytes) + uncompressedSize (4 bytes)
* + segmentCount * size (4 bytes) */ * + segmentCount * size (4 bytes) */
fs = Stream_New(NULL, SrcSize + 7 fs = Stream_New(NULL, SrcSize + 7
+ (SrcSize/ZGFX_SEGMENTED_MAXSIZE + 1) * 4); + (SrcSize / ZGFX_SEGMENTED_MAXSIZE + 1) * 4);
if (!fs) if (!fs)
{ {
@ -438,7 +439,8 @@ static INLINE UINT32 rdpgfx_estimate_h264_avc420(
* *
* @return estimated size * @return estimated size
*/ */
static INLINE UINT32 rdpgfx_estimate_surface_command(RDPGFX_SURFACE_COMMAND* cmd) static INLINE UINT32 rdpgfx_estimate_surface_command(RDPGFX_SURFACE_COMMAND*
cmd)
{ {
RDPGFX_AVC420_BITMAP_STREAM* havc420 = NULL; RDPGFX_AVC420_BITMAP_STREAM* havc420 = NULL;
RDPGFX_AVC444_BITMAP_STREAM* havc444 = NULL; RDPGFX_AVC444_BITMAP_STREAM* havc444 = NULL;
@ -450,10 +452,12 @@ static INLINE UINT32 rdpgfx_estimate_surface_command(RDPGFX_SURFACE_COMMAND* cmd
case RDPGFX_CODECID_CAPROGRESSIVE: case RDPGFX_CODECID_CAPROGRESSIVE:
case RDPGFX_CODECID_CAPROGRESSIVE_V2: case RDPGFX_CODECID_CAPROGRESSIVE_V2:
return RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE + cmd->length; return RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE + cmd->length;
case RDPGFX_CODECID_AVC420: case RDPGFX_CODECID_AVC420:
havc420 = (RDPGFX_AVC420_BITMAP_STREAM*)cmd->extra; havc420 = (RDPGFX_AVC420_BITMAP_STREAM*)cmd->extra;
h264Size = rdpgfx_estimate_h264_avc420(havc420); h264Size = rdpgfx_estimate_h264_avc420(havc420);
return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size; return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size;
case RDPGFX_CODECID_AVC444: case RDPGFX_CODECID_AVC444:
havc444 = (RDPGFX_AVC444_BITMAP_STREAM*)cmd->extra; havc444 = (RDPGFX_AVC444_BITMAP_STREAM*)cmd->extra;
h264Size = sizeof(UINT32); /* cbAvc420EncodedBitstream1 */ h264Size = sizeof(UINT32); /* cbAvc420EncodedBitstream1 */
@ -469,6 +473,7 @@ static INLINE UINT32 rdpgfx_estimate_surface_command(RDPGFX_SURFACE_COMMAND* cmd
} }
return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size; return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size;
default: default:
return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + cmd->length; return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + cmd->length;
} }
@ -558,7 +563,8 @@ static INLINE UINT rdpgfx_write_h264_avc420(wStream* s,
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpgfx_write_surface_command(wStream* s, RDPGFX_SURFACE_COMMAND* cmd) static UINT rdpgfx_write_surface_command(wStream* s,
RDPGFX_SURFACE_COMMAND* cmd)
{ {
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
RDPGFX_AVC420_BITMAP_STREAM* havc420 = NULL; RDPGFX_AVC420_BITMAP_STREAM* havc420 = NULL;
@ -784,7 +790,8 @@ error:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpgfx_send_delete_encoding_context_pdu(RdpgfxServerContext* context, static UINT rdpgfx_send_delete_encoding_context_pdu(RdpgfxServerContext*
context,
RDPGFX_DELETE_ENCODING_CONTEXT_PDU* pdu) RDPGFX_DELETE_ENCODING_CONTEXT_PDU* pdu)
{ {
wStream* s = rdpgfx_server_single_packet_new( wStream* s = rdpgfx_server_single_packet_new(
@ -1249,33 +1256,33 @@ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s)
switch (header.cmdId) switch (header.cmdId)
{ {
case RDPGFX_CMDID_FRAMEACKNOWLEDGE: case RDPGFX_CMDID_FRAMEACKNOWLEDGE:
if ((error = rdpgfx_recv_frame_acknowledge_pdu(context, s))) if ((error = rdpgfx_recv_frame_acknowledge_pdu(context, s)))
WLog_ERR(TAG, "rdpgfx_recv_frame_acknowledge_pdu " WLog_ERR(TAG, "rdpgfx_recv_frame_acknowledge_pdu "
"failed with error %lu!", error); "failed with error %lu!", error);
break; break;
case RDPGFX_CMDID_CACHEIMPORTOFFER:
case RDPGFX_CMDID_CACHEIMPORTOFFER:
if ((error = rdpgfx_recv_cache_import_offer_pdu(context, s))) if ((error = rdpgfx_recv_cache_import_offer_pdu(context, s)))
WLog_ERR(TAG, "rdpgfx_recv_cache_import_offer_pdu " WLog_ERR(TAG, "rdpgfx_recv_cache_import_offer_pdu "
"failed with error %lu!", error); "failed with error %lu!", error);
break; break;
case RDPGFX_CMDID_CAPSADVERTISE:
case RDPGFX_CMDID_CAPSADVERTISE:
if ((error = rdpgfx_recv_caps_advertise_pdu(context, s))) if ((error = rdpgfx_recv_caps_advertise_pdu(context, s)))
WLog_ERR(TAG, "rdpgfx_recv_caps_advertise_pdu " WLog_ERR(TAG, "rdpgfx_recv_caps_advertise_pdu "
"failed with error %lu!", error); "failed with error %lu!", error);
break; break;
case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE:
case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE:
if ((error = rdpgfx_recv_qoe_frame_acknowledge_pdu(context, s))) if ((error = rdpgfx_recv_qoe_frame_acknowledge_pdu(context, s)))
WLog_ERR(TAG, "rdpgfx_recv_qoe_frame_acknowledge_pdu " WLog_ERR(TAG, "rdpgfx_recv_qoe_frame_acknowledge_pdu "
"failed with error %lu!", error); "failed with error %lu!", error);
break; break;
default: default:
error = CHANNEL_RC_BAD_PROC; error = CHANNEL_RC_BAD_PROC;
break; break;
@ -1313,7 +1320,6 @@ static void* rdpgfx_server_thread_func(void* arg)
buffer = NULL; buffer = NULL;
BytesReturned = 0; BytesReturned = 0;
nCount = 0; nCount = 0;
freerdp_channel_init_thread_context(context->rdpcontext); freerdp_channel_init_thread_context(context->rdpcontext);
events[nCount++] = priv->stopEvent; events[nCount++] = priv->stopEvent;
events[nCount++] = priv->channelEvent; events[nCount++] = priv->channelEvent;
@ -1369,7 +1375,7 @@ static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
return FALSE; return FALSE;
} }
priv->SessionId = (DWORD) *pSessionId; priv->SessionId = (DWORD) * pSessionId;
WTSFreeMemory(pSessionId); WTSFreeMemory(pSessionId);
priv->rdpgfx_channel = WTSVirtualChannelOpenEx(priv->SessionId, priv->rdpgfx_channel = WTSVirtualChannelOpenEx(priv->SessionId,
RDPGFX_DVC_CHANNEL_NAME, RDPGFX_DVC_CHANNEL_NAME,

View File

@ -113,7 +113,6 @@ static void* rdpsnd_schedule_thread(void* arg)
HANDLE events[2]; HANDLE events[2];
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
DWORD status; DWORD status;
freerdp_channel_init_thread_context(rdpsnd->rdpcontext); freerdp_channel_init_thread_context(rdpsnd->rdpcontext);
events[0] = MessageQueue_Event(rdpsnd->MsgPipe->Out); events[0] = MessageQueue_Event(rdpsnd->MsgPipe->Out);
events[1] = rdpsnd->stopEvent; events[1] = rdpsnd->stopEvent;
@ -1246,8 +1245,8 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg)
wMessage message; wMessage message;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg; rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg;
UINT error; UINT error;
freerdp_channel_init_thread_context(rdpsnd->rdpcontext); freerdp_channel_init_thread_context(rdpsnd->rdpcontext);
if ((error = rdpsnd_process_connect(rdpsnd))) if ((error = rdpsnd_process_connect(rdpsnd)))
{ {
WLog_ERR(TAG, "error connecting sound channel"); WLog_ERR(TAG, "error connecting sound channel");

View File

@ -46,11 +46,9 @@ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
UINT16 i; UINT16 i;
BOOL status; BOOL status;
ULONG written; ULONG written;
Stream_Write_UINT8(s, SNDC_FORMATS); Stream_Write_UINT8(s, SNDC_FORMATS);
Stream_Write_UINT8(s, 0); Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s); Stream_Seek_UINT16(s);
Stream_Write_UINT32(s, 0); /* dwFlags */ Stream_Write_UINT32(s, 0); /* dwFlags */
Stream_Write_UINT32(s, 0); /* dwVolume */ Stream_Write_UINT32(s, 0); /* dwVolume */
Stream_Write_UINT32(s, 0); /* dwPitch */ Stream_Write_UINT32(s, 0); /* dwPitch */
@ -62,21 +60,24 @@ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
for (i = 0; i < context->num_server_formats; i++) for (i = 0; i < context->num_server_formats; i++)
{ {
Stream_Write_UINT16(s, context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */ Stream_Write_UINT16(s,
context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
Stream_Write_UINT16(s, context->server_formats[i].nChannels); /* nChannels */ Stream_Write_UINT16(s, context->server_formats[i].nChannels); /* nChannels */
Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */ Stream_Write_UINT32(s,
context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */
Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec * Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec *
context->server_formats[i].nChannels * context->server_formats[i].nChannels *
context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */ context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */
Stream_Write_UINT16(s,
Stream_Write_UINT16(s, context->server_formats[i].nBlockAlign); /* nBlockAlign */ context->server_formats[i].nBlockAlign); /* nBlockAlign */
Stream_Write_UINT16(s, context->server_formats[i].wBitsPerSample); /* wBitsPerSample */ Stream_Write_UINT16(s,
context->server_formats[i].wBitsPerSample); /* wBitsPerSample */
Stream_Write_UINT16(s, context->server_formats[i].cbSize); /* cbSize */ Stream_Write_UINT16(s, context->server_formats[i].cbSize); /* cbSize */
if (context->server_formats[i].cbSize > 0) if (context->server_formats[i].cbSize > 0)
{ {
Stream_Write(s, context->server_formats[i].data, context->server_formats[i].cbSize); Stream_Write(s, context->server_formats[i].data,
context->server_formats[i].cbSize);
} }
} }
@ -84,10 +85,10 @@ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
Stream_SetPosition(s, 2); Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4); Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos); Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
return status ? CHANNEL_RC_OK: ERROR_INTERNAL_ERROR;
} }
/** /**
@ -95,7 +96,8 @@ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s) static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context,
wStream* s)
{ {
UINT16 timestamp; UINT16 timestamp;
BYTE confirmBlockNum; BYTE confirmBlockNum;
@ -110,8 +112,8 @@ static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream
Stream_Read_UINT16(s, timestamp); Stream_Read_UINT16(s, timestamp);
Stream_Read_UINT8(s, confirmBlockNum); Stream_Read_UINT8(s, confirmBlockNum);
Stream_Seek_UINT8(s); Stream_Seek_UINT8(s);
IFCALLRET(context->ConfirmBlock, error, context, confirmBlockNum, timestamp); IFCALLRET(context->ConfirmBlock, error, context, confirmBlockNum, timestamp);
if (error) if (error)
WLog_ERR(TAG, "context->ConfirmBlock failed with error %lu", error); WLog_ERR(TAG, "context->ConfirmBlock failed with error %lu", error);
@ -123,7 +125,8 @@ static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s) static UINT rdpsnd_server_recv_quality_mode(RdpsndServerContext* context,
wStream* s)
{ {
UINT16 quality; UINT16 quality;
@ -180,7 +183,9 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
context->client_formats = (AUDIO_FORMAT *)calloc(context->num_client_formats, sizeof(AUDIO_FORMAT)); context->client_formats = (AUDIO_FORMAT*)calloc(context->num_client_formats,
sizeof(AUDIO_FORMAT));
if (!context->client_formats) if (!context->client_formats)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -196,7 +201,6 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
goto out_free; goto out_free;
} }
Stream_Read_UINT16(s, context->client_formats[i].wFormatTag); Stream_Read_UINT16(s, context->client_formats[i].wFormatTag);
Stream_Read_UINT16(s, context->client_formats[i].nChannels); Stream_Read_UINT16(s, context->client_formats[i].nChannels);
Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec); Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec);
@ -213,7 +217,6 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
error = ERROR_INTERNAL_ERROR; error = ERROR_INTERNAL_ERROR;
goto out_free; goto out_free;
} }
} }
if (context->client_formats[i].wFormatTag != 0) if (context->client_formats[i].wFormatTag != 0)
@ -231,7 +234,6 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
out_free: out_free:
free(context->client_formats); free(context->client_formats);
return error; return error;
@ -243,9 +245,7 @@ static void* rdpsnd_server_thread(void* arg)
HANDLE events[8]; HANDLE events[8];
RdpsndServerContext* context; RdpsndServerContext* context;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
context = (RdpsndServerContext*)arg;
context = (RdpsndServerContext *)arg;
freerdp_channel_init_thread_context(context->rdpcontext); freerdp_channel_init_thread_context(context->rdpcontext);
nCount = 0; nCount = 0;
events[nCount++] = context->priv->channelEvent; events[nCount++] = context->priv->channelEvent;
@ -277,7 +277,6 @@ static void* rdpsnd_server_thread(void* arg)
break; break;
} }
if (status == WAIT_OBJECT_0) if (status == WAIT_OBJECT_0)
break; break;
@ -289,8 +288,11 @@ static void* rdpsnd_server_thread(void* arg)
} }
out: out:
if (error && context->rdpcontext) if (error && context->rdpcontext)
setChannelError(context->rdpcontext, error, "rdpsnd_server_thread reported an error"); setChannelError(context->rdpcontext, error,
"rdpsnd_server_thread reported an error");
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
} }
@ -300,7 +302,8 @@ out:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread) static UINT rdpsnd_server_initialize(RdpsndServerContext* context,
BOOL ownThread)
{ {
context->priv->ownThread = ownThread; context->priv->ownThread = ownThread;
return context->Start(context); return context->Start(context);
@ -311,24 +314,25 @@ static UINT rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThrea
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index) static UINT rdpsnd_server_select_format(RdpsndServerContext* context,
int client_format_index)
{ {
int bs; int bs;
int out_buffer_size; int out_buffer_size;
AUDIO_FORMAT *format; AUDIO_FORMAT* format;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
if (client_format_index < 0 || client_format_index >= context->num_client_formats) if (client_format_index < 0
|| client_format_index >= context->num_client_formats)
{ {
WLog_ERR(TAG, "index %d is not correct.", client_format_index); WLog_ERR(TAG, "index %d is not correct.", client_format_index);
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
EnterCriticalSection(&context->priv->lock); EnterCriticalSection(&context->priv->lock);
context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8; context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8;
context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample * context->src_format.nChannels; context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample *
context->src_format.nChannels;
context->selected_client_format = client_format_index; context->selected_client_format = client_format_index;
format = &context->client_formats[client_format_index]; format = &context->client_formats[client_format_index];
@ -341,34 +345,43 @@ static UINT rdpsnd_server_select_format(RdpsndServerContext* context, int client
if (context->latency <= 0) if (context->latency <= 0)
context->latency = 50; context->latency = 50;
context->priv->out_frames = context->src_format.nSamplesPerSec * context->latency / 1000;
context->priv->out_frames = context->src_format.nSamplesPerSec *
context->latency / 1000;
if (context->priv->out_frames < 1) if (context->priv->out_frames < 1)
context->priv->out_frames = 1; context->priv->out_frames = 1;
switch(format->wFormatTag)
switch (format->wFormatTag)
{ {
case WAVE_FORMAT_DVI_ADPCM: case WAVE_FORMAT_DVI_ADPCM:
bs = (format->nBlockAlign - 4 * format->nChannels) * 4; bs = (format->nBlockAlign - 4 * format->nChannels) * 4;
context->priv->out_frames -= context->priv->out_frames % bs; context->priv->out_frames -= context->priv->out_frames % bs;
if (context->priv->out_frames < bs) if (context->priv->out_frames < bs)
context->priv->out_frames = bs; context->priv->out_frames = bs;
break; break;
case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_ADPCM:
bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2; bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
context->priv->out_frames -= context->priv->out_frames % bs; context->priv->out_frames -= context->priv->out_frames % bs;
if (context->priv->out_frames < bs) if (context->priv->out_frames < bs)
context->priv->out_frames = bs; context->priv->out_frames = bs;
break; break;
} }
context->priv->out_pending_frames = 0;
out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame; context->priv->out_pending_frames = 0;
out_buffer_size = context->priv->out_frames *
context->priv->src_bytes_per_frame;
if (context->priv->out_buffer_size < out_buffer_size) if (context->priv->out_buffer_size < out_buffer_size)
{ {
BYTE *newBuffer; BYTE* newBuffer;
newBuffer = (BYTE*)realloc(context->priv->out_buffer, out_buffer_size);
newBuffer = (BYTE *)realloc(context->priv->out_buffer, out_buffer_size);
if (!newBuffer) if (!newBuffer)
{ {
WLog_ERR(TAG, "realloc failed!"); WLog_ERR(TAG, "realloc failed!");
@ -381,7 +394,6 @@ static UINT rdpsnd_server_select_format(RdpsndServerContext* context, int client
} }
freerdp_dsp_context_reset_adpcm(context->priv->dsp_context); freerdp_dsp_context_reset_adpcm(context->priv->dsp_context);
out: out:
LeaveCriticalSection(&context->priv->lock); LeaveCriticalSection(&context->priv->lock);
return error; return error;
@ -393,7 +405,8 @@ out:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp) static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context,
UINT16 wTimestamp)
{ {
int size; int size;
BYTE* src; BYTE* src;
@ -405,7 +418,6 @@ static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
ULONG written; ULONG written;
wStream* s = context->priv->rdpsnd_pdu; wStream* s = context->priv->rdpsnd_pdu;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
format = &context->client_formats[context->selected_client_format]; format = &context->client_formats[context->selected_client_format];
tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample; tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample;
@ -417,13 +429,15 @@ static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
} }
else else
{ {
context->priv->dsp_context->resample(context->priv->dsp_context, context->priv->out_buffer, context->priv->dsp_context->resample(context->priv->dsp_context,
context->priv->out_buffer,
context->priv->src_bytes_per_sample, context->src_format.nChannels, context->priv->src_bytes_per_sample, context->src_format.nChannels,
context->src_format.nSamplesPerSec, context->priv->out_pending_frames, context->src_format.nSamplesPerSec, context->priv->out_pending_frames,
format->nChannels, format->nSamplesPerSec); format->nChannels, format->nSamplesPerSec);
frames = context->priv->dsp_context->resampled_frames; frames = context->priv->dsp_context->resampled_frames;
src = context->priv->dsp_context->resampled_buffer; src = context->priv->dsp_context->resampled_buffer;
} }
size = frames * tbytes_per_frame; size = frames * tbytes_per_frame;
if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM) if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
@ -442,13 +456,13 @@ static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
} }
context->block_no = (context->block_no + 1) % 256; context->block_no = (context->block_no + 1) % 256;
/* Fill to nBlockAlign for the last audio packet */ /* Fill to nBlockAlign for the last audio packet */
fill_size = 0; fill_size = 0;
if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM || format->wFormatTag == WAVE_FORMAT_ADPCM) && if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM
(context->priv->out_pending_frames < context->priv->out_frames) && ((size % format->nBlockAlign) != 0)) || format->wFormatTag == WAVE_FORMAT_ADPCM) &&
(context->priv->out_pending_frames < context->priv->out_frames)
&& ((size % format->nBlockAlign) != 0))
{ {
fill_size = format->nBlockAlign - (size % format->nBlockAlign); fill_size = format->nBlockAlign - (size % format->nBlockAlign);
} }
@ -458,14 +472,14 @@ static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
Stream_Write_UINT8(s, SNDC_WAVE); /* msgType */ Stream_Write_UINT8(s, SNDC_WAVE); /* msgType */
Stream_Write_UINT8(s, 0); /* bPad */ Stream_Write_UINT8(s, 0); /* bPad */
Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */ Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */
Stream_Write_UINT16(s, wTimestamp); /* wTimeStamp */ Stream_Write_UINT16(s, wTimestamp); /* wTimeStamp */
Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */ Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */
Stream_Write_UINT8(s, context->block_no); /* cBlockNo */ Stream_Write_UINT8(s, context->block_no); /* cBlockNo */
Stream_Seek(s, 3); /* bPad */ Stream_Seek(s, 3); /* bPad */
Stream_Write(s, src, 4); Stream_Write(s, src, 4);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
if (!status) if (!status)
{ {
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
@ -482,13 +496,15 @@ static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
error = CHANNEL_RC_NO_MEMORY; error = CHANNEL_RC_NO_MEMORY;
goto out; goto out;
} }
Stream_Write_UINT32(s, 0); /* bPad */ Stream_Write_UINT32(s, 0); /* bPad */
Stream_Write(s, src + 4, size - 4); Stream_Write(s, src + 4, size - 4);
if (fill_size > 0) if (fill_size > 0)
Stream_Zero(s, fill_size); Stream_Zero(s, fill_size);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
if (!status) if (!status)
{ {
@ -507,12 +523,12 @@ out:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp) static UINT rdpsnd_server_send_samples(RdpsndServerContext* context,
const void* buf, int nframes, UINT16 wTimestamp)
{ {
int cframes; int cframes;
int cframesize; int cframesize;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
EnterCriticalSection(&context->priv->lock); EnterCriticalSection(&context->priv->lock);
if (context->selected_client_format < 0) if (context->selected_client_format < 0)
@ -525,11 +541,12 @@ static UINT rdpsnd_server_send_samples(RdpsndServerContext* context, const void*
while (nframes > 0) while (nframes > 0)
{ {
cframes = MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames); cframes = MIN(nframes, context->priv->out_frames -
context->priv->out_pending_frames);
cframesize = cframes * context->priv->src_bytes_per_frame; cframesize = cframes * context->priv->src_bytes_per_frame;
CopyMemory(context->priv->out_buffer + CopyMemory(context->priv->out_buffer +
(context->priv->out_pending_frames * context->priv->src_bytes_per_frame), buf, cframesize); (context->priv->out_pending_frames * context->priv->src_bytes_per_frame), buf,
cframesize);
buf = (BYTE*) buf + cframesize; buf = (BYTE*) buf + cframesize;
nframes -= cframes; nframes -= cframes;
context->priv->out_pending_frames += cframes; context->priv->out_pending_frames += cframes;
@ -554,27 +571,25 @@ out:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right) static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, int left,
int right)
{ {
int pos; int pos;
BOOL status; BOOL status;
ULONG written; ULONG written;
wStream* s = context->priv->rdpsnd_pdu; wStream* s = context->priv->rdpsnd_pdu;
Stream_Write_UINT8(s, SNDC_SETVOLUME); Stream_Write_UINT8(s, SNDC_SETVOLUME);
Stream_Write_UINT8(s, 0); Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s); Stream_Seek_UINT16(s);
Stream_Write_UINT16(s, left); Stream_Write_UINT16(s, left);
Stream_Write_UINT16(s, right); Stream_Write_UINT16(s, right);
pos = Stream_GetPosition(s); pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2); Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4); Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos); Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
} }
@ -590,7 +605,6 @@ static UINT rdpsnd_server_close(RdpsndServerContext* context)
ULONG written; ULONG written;
wStream* s = context->priv->rdpsnd_pdu; wStream* s = context->priv->rdpsnd_pdu;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
EnterCriticalSection(&context->priv->lock); EnterCriticalSection(&context->priv->lock);
if (context->priv->out_pending_frames > 0) if (context->priv->out_pending_frames > 0)
@ -612,18 +626,16 @@ static UINT rdpsnd_server_close(RdpsndServerContext* context)
return error; return error;
context->selected_client_format = -1; context->selected_client_format = -1;
Stream_Write_UINT8(s, SNDC_CLOSE); Stream_Write_UINT8(s, SNDC_CLOSE);
Stream_Write_UINT8(s, 0); Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s); Stream_Seek_UINT16(s);
pos = Stream_GetPosition(s); pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2); Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4); Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos); Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
} }
@ -634,31 +646,36 @@ static UINT rdpsnd_server_close(RdpsndServerContext* context)
*/ */
static UINT rdpsnd_server_start(RdpsndServerContext* context) static UINT rdpsnd_server_start(RdpsndServerContext* context)
{ {
void *buffer = NULL; void* buffer = NULL;
DWORD bytesReturned; DWORD bytesReturned;
RdpsndServerPrivate *priv = context->priv; RdpsndServerPrivate* priv = context->priv;
UINT error = ERROR_INTERNAL_ERROR; UINT error = ERROR_INTERNAL_ERROR;
priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION,
"rdpsnd");
priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd");
if (!priv->ChannelHandle) if (!priv->ChannelHandle)
{ {
WLog_ERR(TAG, "WTSVirtualChannelOpen failed!"); WLog_ERR(TAG, "WTSVirtualChannelOpen failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE))) if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
&bytesReturned) || (bytesReturned != sizeof(HANDLE)))
{ {
WLog_ERR(TAG, "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)", WLog_ERR(TAG,
"error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)",
bytesReturned); bytesReturned);
if (buffer) if (buffer)
WTSFreeMemory(buffer); WTSFreeMemory(buffer);
goto out_close; goto out_close;
} }
CopyMemory(&priv->channelEvent, buffer, sizeof(HANDLE)); CopyMemory(&priv->channelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer); WTSFreeMemory(buffer);
priv->rdpsnd_pdu = Stream_New(NULL, 4096); priv->rdpsnd_pdu = Stream_New(NULL, 4096);
if (!priv->rdpsnd_pdu) if (!priv->rdpsnd_pdu)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -675,6 +692,7 @@ static UINT rdpsnd_server_start(RdpsndServerContext* context)
if (priv->ownThread) if (priv->ownThread)
{ {
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!context->priv->StopEvent) if (!context->priv->StopEvent)
{ {
WLog_ERR(TAG, "CreateEvent failed!"); WLog_ERR(TAG, "CreateEvent failed!");
@ -683,16 +701,15 @@ static UINT rdpsnd_server_start(RdpsndServerContext* context)
context->priv->Thread = CreateThread(NULL, 0, context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL); (LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
if (!context->priv->Thread) if (!context->priv->Thread)
{ {
WLog_ERR(TAG, "CreateThread failed!"); WLog_ERR(TAG, "CreateThread failed!");
goto out_stopEvent; goto out_stopEvent;
} }
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
out_stopEvent: out_stopEvent:
CloseHandle(context->priv->StopEvent); CloseHandle(context->priv->StopEvent);
context->priv->StopEvent = NULL; context->priv->StopEvent = NULL;
@ -715,6 +732,7 @@ out_close:
static UINT rdpsnd_server_stop(RdpsndServerContext* context) static UINT rdpsnd_server_stop(RdpsndServerContext* context)
{ {
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
if (context->priv->ownThread) if (context->priv->ownThread)
{ {
if (context->priv->StopEvent) if (context->priv->StopEvent)
@ -727,6 +745,7 @@ static UINT rdpsnd_server_stop(RdpsndServerContext* context)
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error; return error;
} }
CloseHandle(context->priv->Thread); CloseHandle(context->priv->Thread);
CloseHandle(context->priv->StopEvent); CloseHandle(context->priv->StopEvent);
} }
@ -743,9 +762,9 @@ static UINT rdpsnd_server_stop(RdpsndServerContext* context)
RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm) RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
{ {
RdpsndServerContext* context; RdpsndServerContext* context;
RdpsndServerPrivate *priv; RdpsndServerPrivate* priv;
context = (RdpsndServerContext*)calloc(1, sizeof(RdpsndServerContext));
context = (RdpsndServerContext *)calloc(1, sizeof(RdpsndServerContext));
if (!context) if (!context)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -753,18 +772,17 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
} }
context->vcm = vcm; context->vcm = vcm;
context->Start = rdpsnd_server_start; context->Start = rdpsnd_server_start;
context->Stop = rdpsnd_server_stop; context->Stop = rdpsnd_server_stop;
context->selected_client_format = -1; context->selected_client_format = -1;
context->Initialize = rdpsnd_server_initialize; context->Initialize = rdpsnd_server_initialize;
context->SelectFormat = rdpsnd_server_select_format; context->SelectFormat = rdpsnd_server_select_format;
context->SendSamples = rdpsnd_server_send_samples; context->SendSamples = rdpsnd_server_send_samples;
context->SetVolume = rdpsnd_server_set_volume; context->SetVolume = rdpsnd_server_set_volume;
context->Close = rdpsnd_server_close; context->Close = rdpsnd_server_close;
context->priv = priv = (RdpsndServerPrivate*)calloc(1,
sizeof(RdpsndServerPrivate));
context->priv = priv = (RdpsndServerPrivate *)calloc(1, sizeof(RdpsndServerPrivate));
if (!priv) if (!priv)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -772,6 +790,7 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
} }
priv->dsp_context = freerdp_dsp_context_new(); priv->dsp_context = freerdp_dsp_context_new();
if (!priv->dsp_context) if (!priv->dsp_context)
{ {
WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); WLog_ERR(TAG, "freerdp_dsp_context_new failed!");
@ -779,6 +798,7 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
} }
priv->input_stream = Stream_New(NULL, 4); priv->input_stream = Stream_New(NULL, 4);
if (!priv->input_stream) if (!priv->input_stream)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -789,7 +809,6 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
priv->waitingHeader = TRUE; priv->waitingHeader = TRUE;
priv->ownThread = TRUE; priv->ownThread = TRUE;
return context; return context;
out_free_dsp: out_free_dsp:
freerdp_dsp_context_free(priv->dsp_context); freerdp_dsp_context_free(priv->dsp_context);
out_free_priv: out_free_priv:
@ -800,11 +819,10 @@ out_free:
} }
void rdpsnd_server_context_reset(RdpsndServerContext *context) void rdpsnd_server_context_reset(RdpsndServerContext* context)
{ {
context->priv->expectedBytes = 4; context->priv->expectedBytes = 4;
context->priv->waitingHeader = TRUE; context->priv->waitingHeader = TRUE;
Stream_SetPosition(context->priv->input_stream, 0); Stream_SetPosition(context->priv->input_stream, 0);
} }
@ -822,13 +840,11 @@ void rdpsnd_server_context_free(RdpsndServerContext* context)
Stream_Free(context->priv->input_stream, TRUE); Stream_Free(context->priv->input_stream, TRUE);
free(context->client_formats); free(context->client_formats);
free(context->priv); free(context->priv);
free(context); free(context);
} }
HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context) HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext* context)
{ {
return context->priv->channelEvent; return context->priv->channelEvent;
} }
@ -847,15 +863,15 @@ HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT rdpsnd_server_handle_messages(RdpsndServerContext *context) UINT rdpsnd_server_handle_messages(RdpsndServerContext* context)
{ {
DWORD bytesReturned; DWORD bytesReturned;
UINT ret = CHANNEL_RC_OK; UINT ret = CHANNEL_RC_OK;
RdpsndServerPrivate* priv = context->priv;
wStream* s = priv->input_stream;
RdpsndServerPrivate *priv = context->priv; if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s),
wStream *s = priv->input_stream; priv->expectedBytes, &bytesReturned))
if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
{ {
if (GetLastError() == ERROR_NO_DATA) if (GetLastError() == ERROR_NO_DATA)
return ERROR_NO_DATA; return ERROR_NO_DATA;
@ -863,6 +879,7 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
WLog_ERR(TAG, "channel connection closed"); WLog_ERR(TAG, "channel connection closed");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
priv->expectedBytes -= bytesReturned; priv->expectedBytes -= bytesReturned;
Stream_Seek(s, bytesReturned); Stream_Seek(s, bytesReturned);
@ -871,15 +888,16 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
Stream_SealLength(s); Stream_SealLength(s);
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
if (priv->waitingHeader) if (priv->waitingHeader)
{ {
/* header case */ /* header case */
Stream_Read_UINT8(s, priv->msgType); Stream_Read_UINT8(s, priv->msgType);
Stream_Seek_UINT8(s); /* bPad */ Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, priv->expectedBytes); Stream_Read_UINT16(s, priv->expectedBytes);
priv->waitingHeader = FALSE; priv->waitingHeader = FALSE;
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
if (priv->expectedBytes) if (priv->expectedBytes)
{ {
if (!Stream_EnsureCapacity(s, priv->expectedBytes)) if (!Stream_EnsureCapacity(s, priv->expectedBytes))
@ -887,6 +905,7 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
} }
@ -914,10 +933,12 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
case SNDC_QUALITYMODE: case SNDC_QUALITYMODE:
ret = rdpsnd_server_recv_quality_mode(context, s); ret = rdpsnd_server_recv_quality_mode(context, s);
Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */ Stream_SetPosition(s,
0); /* in case the Activated callback tries to treat some messages */
if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= 6)) if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= 6))
IFCALL(context->Activated, context); IFCALL(context->Activated, context);
break; break;
default: default:
@ -925,7 +946,7 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
ret = ERROR_INVALID_DATA; ret = ERROR_INVALID_DATA;
break; break;
} }
Stream_SetPosition(s, 0);
Stream_SetPosition(s, 0);
return ret; return ret;
} }

View File

@ -848,7 +848,6 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
wMessage message; wMessage message;
remdeskPlugin* remdesk = (remdeskPlugin*) arg; remdeskPlugin* remdesk = (remdeskPlugin*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(remdesk->rdpcontext); freerdp_channel_init_thread_context(remdesk->rdpcontext);
remdesk_process_connect(remdesk); remdesk_process_connect(remdesk);
@ -1094,8 +1093,10 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
s_TLSPluginContext = remdesk; s_TLSPluginContext = remdesk;
return TRUE; return TRUE;
error_out: error_out:
if (context) if (context)
*(pEntryPointsEx->ppInterface) = NULL; *(pEntryPointsEx->ppInterface) = NULL;
free(remdesk); free(remdesk);
free(context); free(context);
return FALSE; return FALSE;

View File

@ -34,14 +34,13 @@
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_virtual_channel_write(RemdeskServerContext* context, wStream* s) static UINT remdesk_virtual_channel_write(RemdeskServerContext* context,
wStream* s)
{ {
BOOL status; BOOL status;
ULONG BytesWritten = 0; ULONG BytesWritten = 0;
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
(PCHAR) Stream_Buffer(s), Stream_Length(s), &BytesWritten); (PCHAR) Stream_Buffer(s), Stream_Length(s), &BytesWritten);
return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
} }
@ -50,7 +49,8 @@ static UINT remdesk_virtual_channel_write(RemdeskServerContext* context, wStream
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) static UINT remdesk_read_channel_header(wStream* s,
REMDESK_CHANNEL_HEADER* header)
{ {
int status; int status;
UINT32 ChannelNameLen; UINT32 ChannelNameLen;
@ -84,11 +84,9 @@ static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head
} }
ZeroMemory(header->ChannelName, sizeof(header->ChannelName)); ZeroMemory(header->ChannelName, sizeof(header->ChannelName));
pChannelName = (char*) header->ChannelName; pChannelName = (char*) header->ChannelName;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
ChannelNameLen / 2, &pChannelName, 32, NULL, NULL); ChannelNameLen / 2, &pChannelName, 32, NULL, NULL);
Stream_Seek(s, ChannelNameLen); Stream_Seek(s, ChannelNameLen);
if (status <= 0) if (status <= 0)
@ -105,12 +103,12 @@ static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) static UINT remdesk_write_channel_header(wStream* s,
REMDESK_CHANNEL_HEADER* header)
{ {
int index; int index;
UINT32 ChannelNameLen; UINT32 ChannelNameLen;
WCHAR ChannelNameW[32]; WCHAR ChannelNameW[32];
ZeroMemory(ChannelNameW, sizeof(ChannelNameW)); ZeroMemory(ChannelNameW, sizeof(ChannelNameW));
for (index = 0; index < 32; index++) for (index = 0; index < 32; index++)
@ -119,12 +117,9 @@ static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* hea
} }
ChannelNameLen = (strlen(header->ChannelName) + 1) * 2; ChannelNameLen = (strlen(header->ChannelName) + 1) * 2;
Stream_Write_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */ Stream_Write_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */
Stream_Write_UINT32(s, header->DataLength); /* DataLen (4 bytes) */ Stream_Write_UINT32(s, header->DataLength); /* DataLen (4 bytes) */
Stream_Write(s, ChannelNameW, ChannelNameLen); /* ChannelName (variable) */ Stream_Write(s, ChannelNameW, ChannelNameLen); /* ChannelName (variable) */
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -136,11 +131,14 @@ static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* hea
static UINT remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader) static UINT remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader)
{ {
UINT error; UINT error;
if ((error = remdesk_write_channel_header(s, (REMDESK_CHANNEL_HEADER*) ctlHeader)))
if ((error = remdesk_write_channel_header(s,
(REMDESK_CHANNEL_HEADER*) ctlHeader)))
{ {
WLog_ERR(TAG, "remdesk_write_channel_header failed with error %lu!", error); WLog_ERR(TAG, "remdesk_write_channel_header failed with error %lu!", error);
return error; return error;
} }
Stream_Write_UINT32(s, ctlHeader->msgType); /* msgType (4 bytes) */ Stream_Write_UINT32(s, ctlHeader->msgType); /* msgType (4 bytes) */
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -150,7 +148,8 @@ static UINT remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize) static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader,
UINT32 msgType, UINT32 msgSize)
{ {
ctlHeader->msgType = msgType; ctlHeader->msgType = msgType;
strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME); strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME);
@ -163,21 +162,23 @@ static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msg
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_send_ctl_result_pdu(RemdeskServerContext* context, UINT32 result) static UINT remdesk_send_ctl_result_pdu(RemdeskServerContext* context,
UINT32 result)
{ {
wStream* s; wStream* s;
REMDESK_CTL_RESULT_PDU pdu; REMDESK_CTL_RESULT_PDU pdu;
UINT error; UINT error;
pdu.result = result; pdu.result = result;
if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_RESULT, 4))) if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_RESULT,
4)))
{ {
WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %lu!", error); WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %lu!", error);
return error; return error;
} }
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -190,16 +191,14 @@ static UINT remdesk_send_ctl_result_pdu(RemdeskServerContext* context, UINT32 re
goto out; goto out;
} }
Stream_Write_UINT32(s, pdu.result); /* result (4 bytes) */ Stream_Write_UINT32(s, pdu.result); /* result (4 bytes) */
Stream_SealLength(s); Stream_SealLength(s);
if ((error = remdesk_virtual_channel_write(context, s))) if ((error = remdesk_virtual_channel_write(context, s)))
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error); WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);
out: out:
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
return error; return error;
} }
@ -214,7 +213,8 @@ static UINT remdesk_send_ctl_version_info_pdu(RemdeskServerContext* context)
REMDESK_CTL_VERSION_INFO_PDU pdu; REMDESK_CTL_VERSION_INFO_PDU pdu;
UINT error; UINT error;
if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERSIONINFO, 8))) if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader),
REMDESK_CTL_VERSIONINFO, 8)))
{ {
WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %lu!", error); WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %lu!", error);
return error; return error;
@ -222,8 +222,8 @@ static UINT remdesk_send_ctl_version_info_pdu(RemdeskServerContext* context)
pdu.versionMajor = 1; pdu.versionMajor = 1;
pdu.versionMinor = 2; pdu.versionMinor = 2;
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -238,14 +238,13 @@ static UINT remdesk_send_ctl_version_info_pdu(RemdeskServerContext* context)
Stream_Write_UINT32(s, pdu.versionMajor); /* versionMajor (4 bytes) */ Stream_Write_UINT32(s, pdu.versionMajor); /* versionMajor (4 bytes) */
Stream_Write_UINT32(s, pdu.versionMinor); /* versionMinor (4 bytes) */ Stream_Write_UINT32(s, pdu.versionMinor); /* versionMinor (4 bytes) */
Stream_SealLength(s); Stream_SealLength(s);
if ((error = remdesk_virtual_channel_write(context, s))) if ((error = remdesk_virtual_channel_write(context, s)))
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error); WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);
out: out:
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
return error; return error;
} }
@ -254,7 +253,8 @@ out:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) static UINT remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context,
wStream* s, REMDESK_CHANNEL_HEADER* header)
{ {
UINT32 versionMajor; UINT32 versionMajor;
UINT32 versionMinor; UINT32 versionMinor;
@ -267,7 +267,6 @@ static UINT remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context, wSt
Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */ Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */
Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */ Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -276,7 +275,8 @@ static UINT remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context, wSt
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) static UINT remdesk_recv_ctl_remote_control_desktop_pdu(
RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header)
{ {
int status; int status;
int cchStringW; int cchStringW;
@ -286,9 +286,7 @@ static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* co
WCHAR* raConnectionStringW = NULL; WCHAR* raConnectionStringW = NULL;
REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu; REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu;
UINT error; UINT error;
msgLength = header->DataLength - 4; msgLength = header->DataLength - 4;
pStringW = (WCHAR*) Stream_Pointer(s); pStringW = (WCHAR*) Stream_Pointer(s);
raConnectionStringW = pStringW; raConnectionStringW = pStringW;
cchStringW = 0; cchStringW = 0;
@ -304,9 +302,7 @@ static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* co
cchStringW++; cchStringW++;
cbRaConnectionStringW = cchStringW * 2; cbRaConnectionStringW = cchStringW * 2;
pdu.raConnectionString = NULL; pdu.raConnectionString = NULL;
status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW, status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW,
cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL); cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL);
@ -331,7 +327,8 @@ static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* co
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context,
wStream* s, REMDESK_CHANNEL_HEADER* header)
{ {
int status; int status;
int cchStringW; int cchStringW;
@ -342,9 +339,7 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
int cbRaConnectionStringW = 0; int cbRaConnectionStringW = 0;
WCHAR* raConnectionStringW = NULL; WCHAR* raConnectionStringW = NULL;
REMDESK_CTL_AUTHENTICATE_PDU pdu; REMDESK_CTL_AUTHENTICATE_PDU pdu;
msgLength = header->DataLength - 4; msgLength = header->DataLength - 4;
pStringW = (WCHAR*) Stream_Pointer(s); pStringW = (WCHAR*) Stream_Pointer(s);
raConnectionStringW = pStringW; raConnectionStringW = pStringW;
cchStringW = 0; cchStringW = 0;
@ -360,7 +355,6 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
cchStringW++; cchStringW++;
cbRaConnectionStringW = cchStringW * 2; cbRaConnectionStringW = cchStringW * 2;
pStringW += cchStringW; pStringW += cchStringW;
expertBlobW = pStringW; expertBlobW = pStringW;
cchStringW = 0; cchStringW = 0;
@ -376,9 +370,7 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
cchStringW++; cchStringW++;
cbExpertBlobW = cchStringW * 2; cbExpertBlobW = cchStringW * 2;
pdu.raConnectionString = NULL; pdu.raConnectionString = NULL;
status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW, status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW,
cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL); cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL);
@ -389,7 +381,6 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
} }
pdu.expertBlob = NULL; pdu.expertBlob = NULL;
status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW, status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW,
cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL); cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL);
@ -404,7 +395,6 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
pdu.raConnectionString, pdu.expertBlob); pdu.raConnectionString, pdu.expertBlob);
free(pdu.raConnectionString); free(pdu.raConnectionString);
free(pdu.expertBlob); free(pdu.expertBlob);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -413,7 +403,8 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context,
wStream* s, REMDESK_CHANNEL_HEADER* header)
{ {
int status; int status;
int cbExpertBlobW = 0; int cbExpertBlobW = 0;
@ -430,8 +421,8 @@ static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context,
pdu.expertBlob = NULL; pdu.expertBlob = NULL;
expertBlobW = (WCHAR*) Stream_Pointer(s); expertBlobW = (WCHAR*) Stream_Pointer(s);
cbExpertBlobW = header->DataLength - 4; cbExpertBlobW = header->DataLength - 4;
status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW, cbExpertBlobW / 2,
status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW, cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL); &pdu.expertBlob, 0, NULL, NULL);
if (status <= 0) if (status <= 0)
{ {
@ -440,6 +431,7 @@ static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context,
} }
WLog_INFO(TAG, "ExpertBlob: %s", pdu.expertBlob); WLog_INFO(TAG, "ExpertBlob: %s", pdu.expertBlob);
if ((error = remdesk_send_ctl_result_pdu(context, 0))) if ((error = remdesk_send_ctl_result_pdu(context, 0)))
WLog_ERR(TAG, "remdesk_send_ctl_result_pdu failed with error %lu!", error); WLog_ERR(TAG, "remdesk_send_ctl_result_pdu failed with error %lu!", error);
@ -451,7 +443,8 @@ static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context,
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s,
REMDESK_CHANNEL_HEADER* header)
{ {
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
UINT32 msgType = 0; UINT32 msgType = 0;
@ -470,28 +463,34 @@ static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMD
case REMDESK_CTL_REMOTE_CONTROL_DESKTOP: case REMDESK_CTL_REMOTE_CONTROL_DESKTOP:
if ((error = remdesk_recv_ctl_remote_control_desktop_pdu(context, s, header))) if ((error = remdesk_recv_ctl_remote_control_desktop_pdu(context, s, header)))
{ {
WLog_ERR(TAG, "remdesk_recv_ctl_remote_control_desktop_pdu failed with error %lu!", error); WLog_ERR(TAG,
"remdesk_recv_ctl_remote_control_desktop_pdu failed with error %lu!", error);
return error; return error;
} }
break; break;
case REMDESK_CTL_AUTHENTICATE: case REMDESK_CTL_AUTHENTICATE:
if ((error = remdesk_recv_ctl_authenticate_pdu(context, s, header))) if ((error = remdesk_recv_ctl_authenticate_pdu(context, s, header)))
{ {
WLog_ERR(TAG, "remdesk_recv_ctl_authenticate_pdu failed with error %lu!", error); WLog_ERR(TAG, "remdesk_recv_ctl_authenticate_pdu failed with error %lu!",
error);
return error; return error;
} }
break; break;
case REMDESK_CTL_DISCONNECT: case REMDESK_CTL_DISCONNECT:
break; break;
case REMDESK_CTL_VERSIONINFO: case REMDESK_CTL_VERSIONINFO:
if((error = remdesk_recv_ctl_version_info_pdu(context, s, header))) if ((error = remdesk_recv_ctl_version_info_pdu(context, s, header)))
{ {
WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %lu!", error); WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %lu!",
error);
return error; return error;
} }
break; break;
case REMDESK_CTL_ISCONNECTED: case REMDESK_CTL_ISCONNECTED:
@ -500,9 +499,11 @@ static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMD
case REMDESK_CTL_VERIFY_PASSWORD: case REMDESK_CTL_VERIFY_PASSWORD:
if ((error = remdesk_recv_ctl_verify_password_pdu(context, s, header))) if ((error = remdesk_recv_ctl_verify_password_pdu(context, s, header)))
{ {
WLog_ERR(TAG, "remdesk_recv_ctl_verify_password_pdu failed with error %lu!", error); WLog_ERR(TAG, "remdesk_recv_ctl_verify_password_pdu failed with error %lu!",
error);
return error; return error;
} }
break; break;
case REMDESK_CTL_EXPERT_ON_VISTA: case REMDESK_CTL_EXPERT_ON_VISTA:
@ -531,11 +532,11 @@ static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMD
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s) static UINT remdesk_server_receive_pdu(RemdeskServerContext* context,
wStream* s)
{ {
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
REMDESK_CHANNEL_HEADER header; REMDESK_CHANNEL_HEADER header;
#if 0 #if 0
WLog_INFO(TAG, "RemdeskReceive: %d", Stream_GetRemainingLength(s)); WLog_INFO(TAG, "RemdeskReceive: %d", Stream_GetRemainingLength(s));
winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s)); winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s));
@ -547,7 +548,6 @@ static UINT remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s
return error; return error;
} }
if (strcmp(header.ChannelName, "RC_CTL") == 0) if (strcmp(header.ChannelName, "RC_CTL") == 0)
{ {
if ((error = remdesk_recv_ctl_pdu(context, s, &header))) if ((error = remdesk_recv_ctl_pdu(context, s, &header)))
@ -558,27 +558,21 @@ static UINT remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s
} }
else if (strcmp(header.ChannelName, "70") == 0) else if (strcmp(header.ChannelName, "70") == 0)
{ {
} }
else if (strcmp(header.ChannelName, "71") == 0) else if (strcmp(header.ChannelName, "71") == 0)
{ {
} }
else if (strcmp(header.ChannelName, ".") == 0) else if (strcmp(header.ChannelName, ".") == 0)
{ {
} }
else if (strcmp(header.ChannelName, "1000.") == 0) else if (strcmp(header.ChannelName, "1000.") == 0)
{ {
} }
else if (strcmp(header.ChannelName, "RA_FX") == 0) else if (strcmp(header.ChannelName, "RA_FX") == 0)
{ {
} }
else else
{ {
} }
return error; return error;
@ -597,15 +591,13 @@ static void* remdesk_server_thread(void* arg)
DWORD BytesReturned; DWORD BytesReturned;
RemdeskServerContext* context; RemdeskServerContext* context;
UINT error; UINT error;
context = (RemdeskServerContext*) arg; context = (RemdeskServerContext*) arg;
freerdp_channel_init_thread_context(context->rdpcontext); freerdp_channel_init_thread_context(context->rdpcontext);
buffer = NULL; buffer = NULL;
BytesReturned = 0; BytesReturned = 0;
ChannelEvent = NULL; ChannelEvent = NULL;
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -613,7 +605,8 @@ static void* remdesk_server_thread(void* arg)
goto out; goto out;
} }
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
&buffer, &BytesReturned) == TRUE)
{ {
if (BytesReturned == sizeof(HANDLE)) if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
@ -633,7 +626,8 @@ static void* remdesk_server_thread(void* arg)
if ((error = remdesk_send_ctl_version_info_pdu(context))) if ((error = remdesk_send_ctl_version_info_pdu(context)))
{ {
WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu!", error); WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu!",
error);
goto out; goto out;
} }
@ -657,7 +651,6 @@ static void* remdesk_server_thread(void* arg)
break; break;
} }
if (status == WAIT_OBJECT_0) if (status == WAIT_OBJECT_0)
{ {
break; break;
@ -688,11 +681,13 @@ static void* remdesk_server_thread(void* arg)
{ {
Stream_SealLength(s); Stream_SealLength(s);
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
if ((error = remdesk_server_receive_pdu(context, s))) if ((error = remdesk_server_receive_pdu(context, s)))
{ {
WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %lu!", error); WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %lu!", error);
break; break;
} }
Stream_SetPosition(s, 0); Stream_SetPosition(s, 0);
} }
} }
@ -700,8 +695,10 @@ static void* remdesk_server_thread(void* arg)
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
out: out:
if (error && context->rdpcontext) if (error && context->rdpcontext)
setChannelError(context->rdpcontext, error, "remdesk_server_thread reported an error"); setChannelError(context->rdpcontext, error,
"remdesk_server_thread reported an error");
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
@ -714,7 +711,8 @@ out:
*/ */
static UINT remdesk_server_start(RemdeskServerContext* context) static UINT remdesk_server_start(RemdeskServerContext* context)
{ {
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "remdesk"); context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm,
WTS_CURRENT_SESSION, "remdesk");
if (!context->priv->ChannelHandle) if (!context->priv->ChannelHandle)
{ {
@ -748,7 +746,6 @@ static UINT remdesk_server_start(RemdeskServerContext* context)
static UINT remdesk_server_stop(RemdeskServerContext* context) static UINT remdesk_server_stop(RemdeskServerContext* context)
{ {
UINT error; UINT error;
SetEvent(context->priv->StopEvent); SetEvent(context->priv->StopEvent);
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED) if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
@ -757,24 +754,21 @@ static UINT remdesk_server_stop(RemdeskServerContext* context)
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error; return error;
} }
CloseHandle(context->priv->Thread);
CloseHandle(context->priv->Thread);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
RemdeskServerContext* remdesk_server_context_new(HANDLE vcm) RemdeskServerContext* remdesk_server_context_new(HANDLE vcm)
{ {
RemdeskServerContext* context; RemdeskServerContext* context;
context = (RemdeskServerContext*) calloc(1, sizeof(RemdeskServerContext)); context = (RemdeskServerContext*) calloc(1, sizeof(RemdeskServerContext));
if (context) if (context)
{ {
context->vcm = vcm; context->vcm = vcm;
context->Start = remdesk_server_start; context->Start = remdesk_server_start;
context->Stop = remdesk_server_stop; context->Stop = remdesk_server_stop;
context->priv = (RemdeskServerPrivate*) calloc(1, sizeof(RemdeskServerPrivate)); context->priv = (RemdeskServerPrivate*) calloc(1, sizeof(RemdeskServerPrivate));
if (!context->priv) if (!context->priv)
@ -782,6 +776,7 @@ RemdeskServerContext* remdesk_server_context_new(HANDLE vcm)
free(context); free(context);
return NULL; return NULL;
} }
context->priv->Version = 1; context->priv->Version = 1;
} }

View File

@ -65,7 +65,7 @@ struct _SERIAL_DEVICE
wMessageQueue* MainIrpQueue; wMessageQueue* MainIrpQueue;
/* one thread per pending IRP and indexed according their CompletionId */ /* one thread per pending IRP and indexed according their CompletionId */
wListDictionary *IrpThreads; wListDictionary* IrpThreads;
UINT32 IrpThreadToBeTerminatedCount; UINT32 IrpThreadToBeTerminatedCount;
CRITICAL_SECTION TerminatingIrpThreadsLock; CRITICAL_SECTION TerminatingIrpThreadsLock;
rdpContext* rdpcontext; rdpContext* rdpcontext;
@ -75,15 +75,14 @@ typedef struct _IRP_THREAD_DATA IRP_THREAD_DATA;
struct _IRP_THREAD_DATA struct _IRP_THREAD_DATA
{ {
SERIAL_DEVICE *serial; SERIAL_DEVICE* serial;
IRP *irp; IRP* irp;
}; };
static UINT32 _GetLastErrorToIoStatus(SERIAL_DEVICE* serial) static UINT32 _GetLastErrorToIoStatus(SERIAL_DEVICE* serial)
{ {
/* http://msdn.microsoft.com/en-us/library/ff547466%28v=vs.85%29.aspx#generic_status_values_for_serial_device_control_requests */ /* http://msdn.microsoft.com/en-us/library/ff547466%28v=vs.85%29.aspx#generic_status_values_for_serial_device_control_requests */
switch (GetLastError())
switch(GetLastError())
{ {
case ERROR_BAD_DEVICE: case ERROR_BAD_DEVICE:
return STATUS_INVALID_DEVICE_REQUEST; return STATUS_INVALID_DEVICE_REQUEST;
@ -117,11 +116,11 @@ static UINT32 _GetLastErrorToIoStatus(SERIAL_DEVICE* serial)
case ERROR_TIMEOUT: case ERROR_TIMEOUT:
return STATUS_TIMEOUT; return STATUS_TIMEOUT;
/* no default */ /* no default */
} }
WLog_Print(serial->log, WLOG_DEBUG, "unexpected last-error: 0x%lx", GetLastError()); WLog_Print(serial->log, WLOG_DEBUG, "unexpected last-error: 0x%lx",
GetLastError());
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
@ -131,19 +130,16 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
DWORD SharedAccess; DWORD SharedAccess;
DWORD CreateDisposition; DWORD CreateDisposition;
UINT32 PathLength; UINT32 PathLength;
Stream_Read_UINT32(irp->input, DesiredAccess); /* DesiredAccess (4 bytes) */ Stream_Read_UINT32(irp->input, DesiredAccess); /* DesiredAccess (4 bytes) */
Stream_Seek_UINT64(irp->input); /* AllocationSize (8 bytes) */ Stream_Seek_UINT64(irp->input); /* AllocationSize (8 bytes) */
Stream_Seek_UINT32(irp->input); /* FileAttributes (4 bytes) */ Stream_Seek_UINT32(irp->input); /* FileAttributes (4 bytes) */
Stream_Read_UINT32(irp->input, SharedAccess); /* SharedAccess (4 bytes) */ Stream_Read_UINT32(irp->input, SharedAccess); /* SharedAccess (4 bytes) */
Stream_Read_UINT32(irp->input, CreateDisposition); /* CreateDisposition (4 bytes) */ Stream_Read_UINT32(irp->input,
CreateDisposition); /* CreateDisposition (4 bytes) */
Stream_Seek_UINT32(irp->input); /* CreateOptions (4 bytes) */ Stream_Seek_UINT32(irp->input); /* CreateOptions (4 bytes) */
Stream_Read_UINT32(irp->input, PathLength); /* PathLength (4 bytes) */ Stream_Read_UINT32(irp->input, PathLength); /* PathLength (4 bytes) */
Stream_Seek(irp->input, PathLength); /* Path (variable) */ Stream_Seek(irp->input, PathLength); /* Path (variable) */
assert(PathLength == 0); /* MS-RDPESP 2.2.2.2 */ assert(PathLength == 0); /* MS-RDPESP 2.2.2.2 */
#ifndef _WIN32 #ifndef _WIN32
/* Windows 2012 server sends on a first call : /* Windows 2012 server sends on a first call :
* DesiredAccess = 0x00100080: SYNCHRONIZE | FILE_READ_ATTRIBUTES * DesiredAccess = 0x00100080: SYNCHRONIZE | FILE_READ_ATTRIBUTES
@ -160,15 +156,14 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
* assert(CreateDisposition == OPEN_EXISTING); * assert(CreateDisposition == OPEN_EXISTING);
* *
*/ */
WLog_Print(serial->log, WLOG_DEBUG,
WLog_Print(serial->log, WLOG_DEBUG, "DesiredAccess: 0x%lX, SharedAccess: 0x%lX, CreateDisposition: 0x%lX", DesiredAccess, SharedAccess, CreateDisposition); "DesiredAccess: 0x%lX, SharedAccess: 0x%lX, CreateDisposition: 0x%lX",
DesiredAccess, SharedAccess, CreateDisposition);
/* FIXME: As of today only the flags below are supported by CommCreateFileA: */ /* FIXME: As of today only the flags below are supported by CommCreateFileA: */
DesiredAccess = GENERIC_READ | GENERIC_WRITE; DesiredAccess = GENERIC_READ | GENERIC_WRITE;
SharedAccess = 0; SharedAccess = 0;
CreateDisposition = OPEN_EXISTING; CreateDisposition = OPEN_EXISTING;
#endif #endif
serial->hComm = CreateFile(serial->device.name, serial->hComm = CreateFile(serial->device.name,
DesiredAccess, DesiredAccess,
SharedAccess, SharedAccess,
@ -179,16 +174,14 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
if (!serial->hComm || (serial->hComm == INVALID_HANDLE_VALUE)) if (!serial->hComm || (serial->hComm == INVALID_HANDLE_VALUE))
{ {
WLog_Print(serial->log, WLOG_WARN, "CreateFile failure: %s last-error: 0x%lX\n", serial->device.name, GetLastError()); WLog_Print(serial->log, WLOG_WARN, "CreateFile failure: %s last-error: 0x%lX\n",
serial->device.name, GetLastError());
irp->IoStatus = STATUS_UNSUCCESSFUL; irp->IoStatus = STATUS_UNSUCCESSFUL;
goto error_handle; goto error_handle;
} }
_comm_setServerSerialDriver(serial->hComm, serial->ServerSerialDriverId); _comm_setServerSerialDriver(serial->hComm, serial->ServerSerialDriverId);
_comm_set_permissive(serial->hComm, serial->permissive); _comm_set_permissive(serial->hComm, serial->permissive);
/* NOTE: binary mode/raw mode required for the redirection. On /* NOTE: binary mode/raw mode required for the redirection. On
* Linux, CommCreateFileA forces this setting. * Linux, CommCreateFileA forces this setting.
*/ */
@ -197,15 +190,13 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
/* GetCommState(serial->hComm, &dcb); */ /* GetCommState(serial->hComm, &dcb); */
/* dcb.fBinary = TRUE; */ /* dcb.fBinary = TRUE; */
/* SetCommState(serial->hComm, &dcb); */ /* SetCommState(serial->hComm, &dcb); */
assert(irp->FileId == 0); assert(irp->FileId == 0);
irp->FileId = irp->devman->id_sequence++; /* FIXME: why not ((WINPR_COMM*)hComm)->fd? */ irp->FileId =
irp->devman->id_sequence++; /* FIXME: why not ((WINPR_COMM*)hComm)->fd? */
irp->IoStatus = STATUS_SUCCESS; irp->IoStatus = STATUS_SUCCESS;
WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %d, FileId: %d) created.",
WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %d, FileId: %d) created.", serial->device.name, irp->device->id, irp->FileId); serial->device.name, irp->device->id, irp->FileId);
error_handle:
error_handle:
Stream_Write_UINT32(irp->output, irp->FileId); /* FileId (4 bytes) */ Stream_Write_UINT32(irp->output, irp->FileId); /* FileId (4 bytes) */
Stream_Write_UINT8(irp->output, 0); /* Information (1 byte) */ Stream_Write_UINT8(irp->output, 0); /* Information (1 byte) */
} }
@ -216,17 +207,17 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
if (!CloseHandle(serial->hComm)) if (!CloseHandle(serial->hComm))
{ {
WLog_Print(serial->log, WLOG_WARN, "CloseHandle failure: %s (%d) closed.", serial->device.name, irp->device->id); WLog_Print(serial->log, WLOG_WARN, "CloseHandle failure: %s (%d) closed.",
serial->device.name, irp->device->id);
irp->IoStatus = STATUS_UNSUCCESSFUL; irp->IoStatus = STATUS_UNSUCCESSFUL;
goto error_handle; goto error_handle;
} }
WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %d, FileId: %d) closed.", serial->device.name, irp->device->id, irp->FileId); WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %d, FileId: %d) closed.",
serial->device.name, irp->device->id, irp->FileId);
serial->hComm = NULL; serial->hComm = NULL;
irp->IoStatus = STATUS_SUCCESS; irp->IoStatus = STATUS_SUCCESS;
error_handle:
error_handle:
Stream_Zero(irp->output, 5); /* Padding (5 bytes) */ Stream_Zero(irp->output, 5); /* Padding (5 bytes) */
} }
@ -241,26 +232,22 @@ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
UINT64 Offset; UINT64 Offset;
BYTE* buffer = NULL; BYTE* buffer = NULL;
DWORD nbRead = 0; DWORD nbRead = 0;
Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */ Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */
Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */ Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
buffer = (BYTE*)calloc(Length, sizeof(BYTE)); buffer = (BYTE*)calloc(Length, sizeof(BYTE));
if (buffer == NULL) if (buffer == NULL)
{ {
irp->IoStatus = STATUS_NO_MEMORY; irp->IoStatus = STATUS_NO_MEMORY;
goto error_handle; goto error_handle;
} }
/* MS-RDPESP 3.2.5.1.4: If the Offset field is not set to 0, the value MUST be ignored /* MS-RDPESP 3.2.5.1.4: If the Offset field is not set to 0, the value MUST be ignored
* assert(Offset == 0); * assert(Offset == 0);
*/ */
WLog_Print(serial->log, WLOG_DEBUG, "reading %d bytes from %s", Length,
serial->device.name);
WLog_Print(serial->log, WLOG_DEBUG, "reading %d bytes from %s", Length, serial->device.name);
/* FIXME: CommReadFile to be replaced by ReadFile */ /* FIXME: CommReadFile to be replaced by ReadFile */
if (CommReadFile(serial->hComm, buffer, Length, &nbRead, NULL)) if (CommReadFile(serial->hComm, buffer, Length, &nbRead, NULL))
@ -269,15 +256,15 @@ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
} }
else else
{ {
WLog_Print(serial->log, WLOG_DEBUG, "read failure to %s, nbRead=%ld, last-error: 0x%lX", serial->device.name, nbRead, GetLastError()); WLog_Print(serial->log, WLOG_DEBUG,
"read failure to %s, nbRead=%ld, last-error: 0x%lX", serial->device.name,
nbRead, GetLastError());
irp->IoStatus = _GetLastErrorToIoStatus(serial); irp->IoStatus = _GetLastErrorToIoStatus(serial);
} }
WLog_Print(serial->log, WLOG_DEBUG, "%lu bytes read from %s", nbRead, serial->device.name); WLog_Print(serial->log, WLOG_DEBUG, "%lu bytes read from %s", nbRead,
serial->device.name);
error_handle: error_handle:
Stream_Write_UINT32(irp->output, nbRead); /* Length (4 bytes) */ Stream_Write_UINT32(irp->output, nbRead); /* Length (4 bytes) */
if (nbRead > 0) if (nbRead > 0)
@ -288,6 +275,7 @@ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
free(buffer); free(buffer);
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Write(irp->output, buffer, nbRead); /* ReadData */ Stream_Write(irp->output, buffer, nbRead); /* ReadData */
} }
@ -300,34 +288,34 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
UINT32 Length; UINT32 Length;
UINT64 Offset; UINT64 Offset;
DWORD nbWritten = 0; DWORD nbWritten = 0;
Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */ Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */
Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */ Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
/* MS-RDPESP 3.2.5.1.5: The Offset field is ignored /* MS-RDPESP 3.2.5.1.5: The Offset field is ignored
* assert(Offset == 0); * assert(Offset == 0);
* *
* Using a serial printer, noticed though this field could be * Using a serial printer, noticed though this field could be
* set. * set.
*/ */
WLog_Print(serial->log, WLOG_DEBUG, "writing %d bytes to %s", Length,
WLog_Print(serial->log, WLOG_DEBUG, "writing %d bytes to %s", Length, serial->device.name); serial->device.name);
/* FIXME: CommWriteFile to be replaced by WriteFile */ /* FIXME: CommWriteFile to be replaced by WriteFile */
if (CommWriteFile(serial->hComm, Stream_Pointer(irp->input), Length, &nbWritten, NULL)) if (CommWriteFile(serial->hComm, Stream_Pointer(irp->input), Length, &nbWritten,
NULL))
{ {
irp->IoStatus = STATUS_SUCCESS; irp->IoStatus = STATUS_SUCCESS;
} }
else else
{ {
WLog_Print(serial->log, WLOG_DEBUG, "write failure to %s, nbWritten=%ld, last-error: 0x%lX", serial->device.name, nbWritten, GetLastError()); WLog_Print(serial->log, WLOG_DEBUG,
"write failure to %s, nbWritten=%ld, last-error: 0x%lX", serial->device.name,
nbWritten, GetLastError());
irp->IoStatus = _GetLastErrorToIoStatus(serial); irp->IoStatus = _GetLastErrorToIoStatus(serial);
} }
WLog_Print(serial->log, WLOG_DEBUG, "%lu bytes written to %s", nbWritten, serial->device.name); WLog_Print(serial->log, WLOG_DEBUG, "%lu bytes written to %s", nbWritten,
serial->device.name);
Stream_Write_UINT32(irp->output, nbWritten); /* Length (4 bytes) */ Stream_Write_UINT32(irp->output, nbWritten); /* Length (4 bytes) */
Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */ Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */
} }
@ -346,13 +334,14 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
UINT32 OutputBufferLength; UINT32 OutputBufferLength;
BYTE* OutputBuffer = NULL; BYTE* OutputBuffer = NULL;
DWORD BytesReturned = 0; DWORD BytesReturned = 0;
Stream_Read_UINT32(irp->input,
Stream_Read_UINT32(irp->input, OutputBufferLength); /* OutputBufferLength (4 bytes) */ OutputBufferLength); /* OutputBufferLength (4 bytes) */
Stream_Read_UINT32(irp->input, InputBufferLength); /* InputBufferLength (4 bytes) */ Stream_Read_UINT32(irp->input,
InputBufferLength); /* InputBufferLength (4 bytes) */
Stream_Read_UINT32(irp->input, IoControlCode); /* IoControlCode (4 bytes) */ Stream_Read_UINT32(irp->input, IoControlCode); /* IoControlCode (4 bytes) */
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
OutputBuffer = (BYTE*)calloc(OutputBufferLength, sizeof(BYTE)); OutputBuffer = (BYTE*)calloc(OutputBufferLength, sizeof(BYTE));
if (OutputBuffer == NULL) if (OutputBuffer == NULL)
{ {
irp->IoStatus = STATUS_NO_MEMORY; irp->IoStatus = STATUS_NO_MEMORY;
@ -360,6 +349,7 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
} }
InputBuffer = (BYTE*)calloc(InputBufferLength, sizeof(BYTE)); InputBuffer = (BYTE*)calloc(InputBufferLength, sizeof(BYTE));
if (InputBuffer == NULL) if (InputBuffer == NULL)
{ {
irp->IoStatus = STATUS_NO_MEMORY; irp->IoStatus = STATUS_NO_MEMORY;
@ -367,32 +357,32 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
} }
Stream_Read(irp->input, InputBuffer, InputBufferLength); Stream_Read(irp->input, InputBuffer, InputBufferLength);
WLog_Print(serial->log, WLOG_DEBUG,
WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl: CompletionId=%d, IoControlCode=[0x%X] %s", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode)); "CommDeviceIoControl: CompletionId=%d, IoControlCode=[0x%X] %s",
irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode));
/* FIXME: CommDeviceIoControl to be replaced by DeviceIoControl() */ /* FIXME: CommDeviceIoControl to be replaced by DeviceIoControl() */
if (CommDeviceIoControl(serial->hComm, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned, NULL)) if (CommDeviceIoControl(serial->hComm, IoControlCode, InputBuffer,
InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned, NULL))
{ {
/* WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl: CompletionId=%d, IoControlCode=[0x%X] %s done", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode)); */ /* WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl: CompletionId=%d, IoControlCode=[0x%X] %s done", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode)); */
irp->IoStatus = STATUS_SUCCESS; irp->IoStatus = STATUS_SUCCESS;
} }
else else
{ {
WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl failure: IoControlCode=[0x%X] %s, last-error: 0x%lX", WLog_Print(serial->log, WLOG_DEBUG,
"CommDeviceIoControl failure: IoControlCode=[0x%X] %s, last-error: 0x%lX",
IoControlCode, _comm_serial_ioctl_name(IoControlCode), GetLastError()); IoControlCode, _comm_serial_ioctl_name(IoControlCode), GetLastError());
irp->IoStatus = _GetLastErrorToIoStatus(serial); irp->IoStatus = _GetLastErrorToIoStatus(serial);
} }
error_handle: error_handle:
/* FIXME: find out whether it's required or not to get /* FIXME: find out whether it's required or not to get
* BytesReturned == OutputBufferLength when * BytesReturned == OutputBufferLength when
* CommDeviceIoControl returns FALSE */ * CommDeviceIoControl returns FALSE */
assert(OutputBufferLength == BytesReturned); assert(OutputBufferLength == BytesReturned);
Stream_Write_UINT32(irp->output,
Stream_Write_UINT32(irp->output, BytesReturned); /* OutputBufferLength (4 bytes) */ BytesReturned); /* OutputBufferLength (4 bytes) */
if (BytesReturned > 0) if (BytesReturned > 0)
{ {
@ -406,6 +396,7 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
Stream_Write(irp->output, OutputBuffer, BytesReturned); /* OutputBuffer */ Stream_Write(irp->output, OutputBuffer, BytesReturned); /* OutputBuffer */
} }
/* FIXME: Why at least Windows 2008R2 gets lost with this /* FIXME: Why at least Windows 2008R2 gets lost with this
* extra byte and likely on a IOCTL_SERIAL_SET_BAUD_RATE? The * extra byte and likely on a IOCTL_SERIAL_SET_BAUD_RATE? The
* extra byte is well required according MS-RDPEFS * extra byte is well required according MS-RDPEFS
@ -414,7 +405,6 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
/* { */ /* { */
/* Stream_Write_UINT8(irp->output, 0); /\* Padding (1 byte) *\/ */ /* Stream_Write_UINT8(irp->output, 0); /\* Padding (1 byte) *\/ */
/* } */ /* } */
free(InputBuffer); free(InputBuffer);
free(OutputBuffer); free(OutputBuffer);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
@ -428,7 +418,8 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
{ {
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
WLog_Print(serial->log, WLOG_DEBUG, "IRP MajorFunction: 0x%04X MinorFunction: 0x%04X\n", WLog_Print(serial->log, WLOG_DEBUG,
"IRP MajorFunction: 0x%04X MinorFunction: 0x%04X\n",
irp->MajorFunction, irp->MinorFunction); irp->MajorFunction, irp->MinorFunction);
switch (irp->MajorFunction) switch (irp->MajorFunction)
@ -444,6 +435,7 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
case IRP_MJ_READ: case IRP_MJ_READ:
if ((error = serial_process_irp_read(serial, irp))) if ((error = serial_process_irp_read(serial, irp)))
WLog_ERR(TAG, "serial_process_irp_read failed with error %lu!", error); WLog_ERR(TAG, "serial_process_irp_read failed with error %lu!", error);
break; break;
case IRP_MJ_WRITE: case IRP_MJ_WRITE:
@ -452,22 +444,24 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_DEVICE_CONTROL:
if ((error = serial_process_irp_device_control(serial, irp))) if ((error = serial_process_irp_device_control(serial, irp)))
WLog_ERR(TAG, "serial_process_irp_device_control failed with error %lu!", error); WLog_ERR(TAG, "serial_process_irp_device_control failed with error %lu!",
error);
break; break;
default: default:
irp->IoStatus = STATUS_NOT_SUPPORTED; irp->IoStatus = STATUS_NOT_SUPPORTED;
break; break;
} }
return error; return error;
} }
static void* irp_thread_func(void* arg) static void* irp_thread_func(void* arg)
{ {
IRP_THREAD_DATA *data = (IRP_THREAD_DATA*)arg; IRP_THREAD_DATA* data = (IRP_THREAD_DATA*)arg;
UINT error; UINT error;
freerdp_channel_init_thread_context(data->serial->rdpcontext); freerdp_channel_init_thread_context(data->serial->rdpcontext);
/* blocks until the end of the request */ /* blocks until the end of the request */
@ -479,33 +473,29 @@ static void* irp_thread_func(void* arg)
EnterCriticalSection(&data->serial->TerminatingIrpThreadsLock); EnterCriticalSection(&data->serial->TerminatingIrpThreadsLock);
data->serial->IrpThreadToBeTerminatedCount++; data->serial->IrpThreadToBeTerminatedCount++;
error = data->irp->Complete(data->irp); error = data->irp->Complete(data->irp);
LeaveCriticalSection(&data->serial->TerminatingIrpThreadsLock); LeaveCriticalSection(&data->serial->TerminatingIrpThreadsLock);
error_out: error_out:
if (error && data->serial->rdpcontext) if (error && data->serial->rdpcontext)
setChannelError(data->serial->rdpcontext, error, "irp_thread_func reported an error"); setChannelError(data->serial->rdpcontext, error,
"irp_thread_func reported an error");
/* NB: At this point, the server might already being reusing /* NB: At this point, the server might already being reusing
* the CompletionId whereas the thread is not yet * the CompletionId whereas the thread is not yet
* terminated */ * terminated */
free(data); free(data);
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
} }
static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp) static void create_irp_thread(SERIAL_DEVICE* serial, IRP* irp)
{ {
IRP_THREAD_DATA *data = NULL; IRP_THREAD_DATA* data = NULL;
HANDLE irpThread; HANDLE irpThread;
HANDLE previousIrpThread; HANDLE previousIrpThread;
uintptr_t key; uintptr_t key;
/* for a test/debug purpose, uncomment the code below to get a /* for a test/debug purpose, uncomment the code below to get a
* single thread for all IRPs. NB: two IRPs could not be * single thread for all IRPs. NB: two IRPs could not be
* processed at the same time, typically two concurent * processed at the same time, typically two concurent
@ -513,65 +503,57 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
/* serial_process_irp(serial, irp); */ /* serial_process_irp(serial, irp); */
/* irp->Complete(irp); */ /* irp->Complete(irp); */
/* return; */ /* return; */
/* NOTE: for good or bad, this implementation relies on the /* NOTE: for good or bad, this implementation relies on the
* server to avoid a flooding of requests. see also _purge(). * server to avoid a flooding of requests. see also _purge().
*/ */
EnterCriticalSection(&serial->TerminatingIrpThreadsLock); EnterCriticalSection(&serial->TerminatingIrpThreadsLock);
while (serial->IrpThreadToBeTerminatedCount > 0) while (serial->IrpThreadToBeTerminatedCount > 0)
{ {
/* Cleaning up termitating and pending irp /* Cleaning up termitating and pending irp
* threads. See also: irp_thread_func() */ * threads. See also: irp_thread_func() */
HANDLE irpThread; HANDLE irpThread;
ULONG_PTR *ids; ULONG_PTR* ids;
int i, nbIds; int i, nbIds;
nbIds = ListDictionary_GetKeys(serial->IrpThreads, &ids); nbIds = ListDictionary_GetKeys(serial->IrpThreads, &ids);
for (i=0; i<nbIds; i++)
for (i = 0; i < nbIds; i++)
{ {
/* Checking if ids[i] is terminating or pending */ /* Checking if ids[i] is terminating or pending */
DWORD waitResult; DWORD waitResult;
ULONG_PTR id = ids[i]; ULONG_PTR id = ids[i];
irpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)id); irpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)id);
/* FIXME: not quite sure a zero timeout is a good thing to check whether a thread is stil alived or not */ /* FIXME: not quite sure a zero timeout is a good thing to check whether a thread is stil alived or not */
waitResult = WaitForSingleObject(irpThread, 0); waitResult = WaitForSingleObject(irpThread, 0);
if (waitResult == WAIT_OBJECT_0) if (waitResult == WAIT_OBJECT_0)
{ {
/* terminating thread */ /* terminating thread */
/* WLog_Print(serial->log, WLOG_DEBUG, "IRP thread with CompletionId=%d naturally died", id); */ /* WLog_Print(serial->log, WLOG_DEBUG, "IRP thread with CompletionId=%d naturally died", id); */
CloseHandle(irpThread); CloseHandle(irpThread);
ListDictionary_Remove(serial->IrpThreads, (void*)id); ListDictionary_Remove(serial->IrpThreads, (void*)id);
serial->IrpThreadToBeTerminatedCount--; serial->IrpThreadToBeTerminatedCount--;
} }
else if (waitResult != WAIT_TIMEOUT) else if (waitResult != WAIT_TIMEOUT)
{ {
/* unexpected thread state */ /* unexpected thread state */
WLog_Print(serial->log, WLOG_WARN,
WLog_Print(serial->log, WLOG_WARN, "WaitForSingleObject, got an unexpected result=0x%lX\n", waitResult); "WaitForSingleObject, got an unexpected result=0x%lX\n", waitResult);
assert(FALSE); assert(FALSE);
} }
/* pending thread (but not yet terminating thread) if waitResult == WAIT_TIMEOUT */ /* pending thread (but not yet terminating thread) if waitResult == WAIT_TIMEOUT */
} }
if (serial->IrpThreadToBeTerminatedCount > 0) if (serial->IrpThreadToBeTerminatedCount > 0)
{ {
WLog_Print(serial->log, WLOG_DEBUG, "%d IRP thread(s) not yet terminated", serial->IrpThreadToBeTerminatedCount); WLog_Print(serial->log, WLOG_DEBUG, "%d IRP thread(s) not yet terminated",
serial->IrpThreadToBeTerminatedCount);
Sleep(1); /* 1 ms */ Sleep(1); /* 1 ms */
} }
} }
LeaveCriticalSection(&serial->TerminatingIrpThreadsLock);
LeaveCriticalSection(&serial->TerminatingIrpThreadsLock);
/* NB: At this point and thanks to the synchronization we're /* NB: At this point and thanks to the synchronization we're
* sure that the incoming IRP uses well a recycled * sure that the incoming IRP uses well a recycled
* CompletionId or the server sent again an IRP already posted * CompletionId or the server sent again an IRP already posted
@ -582,22 +564,20 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
* FIXME: behavior documented somewhere? behavior not yet * FIXME: behavior documented somewhere? behavior not yet
* observed with FreeRDP). * observed with FreeRDP).
*/ */
key = irp->CompletionId; key = irp->CompletionId;
previousIrpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)key); previousIrpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)key);
if (previousIrpThread) if (previousIrpThread)
{ {
/* Thread still alived <=> Request still pending */ /* Thread still alived <=> Request still pending */
WLog_Print(serial->log, WLOG_DEBUG,
WLog_Print(serial->log, WLOG_DEBUG, "IRP recall: IRP with the CompletionId=%d not yet completed!", irp->CompletionId); "IRP recall: IRP with the CompletionId=%d not yet completed!",
irp->CompletionId);
assert(FALSE); /* unimplemented */ assert(FALSE); /* unimplemented */
/* TODO: asserts that previousIrpThread handles well /* TODO: asserts that previousIrpThread handles well
* the same request by checking more details. Need an * the same request by checking more details. Need an
* access to the IRP object used by previousIrpThread * access to the IRP object used by previousIrpThread
*/ */
/* TODO: taking over the pending IRP or sending a kind /* TODO: taking over the pending IRP or sending a kind
* of wake up signal to accelerate the pending * of wake up signal to accelerate the pending
* request * request
@ -607,18 +587,16 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
* pComm->PendingEvents |= SERIAL_EV_FREERDP_*; * pComm->PendingEvents |= SERIAL_EV_FREERDP_*;
* } * }
*/ */
irp->Discard(irp); irp->Discard(irp);
return; return;
} }
if (ListDictionary_Count(serial->IrpThreads) >= MAX_IRP_THREADS) if (ListDictionary_Count(serial->IrpThreads) >= MAX_IRP_THREADS)
{ {
WLog_Print(serial->log, WLOG_WARN, "Number of IRP threads threshold reached: %d, keep on anyway", ListDictionary_Count(serial->IrpThreads)); WLog_Print(serial->log, WLOG_WARN,
"Number of IRP threads threshold reached: %d, keep on anyway",
ListDictionary_Count(serial->IrpThreads));
assert(FALSE); /* unimplemented */ assert(FALSE); /* unimplemented */
/* TODO: MAX_IRP_THREADS has been thought to avoid a /* TODO: MAX_IRP_THREADS has been thought to avoid a
* flooding of pending requests. Use * flooding of pending requests. Use
* WaitForMultipleObjects() when available in winpr * WaitForMultipleObjects() when available in winpr
@ -626,10 +604,9 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
*/ */
} }
/* error_handle to be used ... */ /* error_handle to be used ... */
data = (IRP_THREAD_DATA*)calloc(1, sizeof(IRP_THREAD_DATA)); data = (IRP_THREAD_DATA*)calloc(1, sizeof(IRP_THREAD_DATA));
if (data == NULL) if (data == NULL)
{ {
WLog_Print(serial->log, WLOG_WARN, "Could not allocate a new IRP_THREAD_DATA."); WLog_Print(serial->log, WLOG_WARN, "Could not allocate a new IRP_THREAD_DATA.");
@ -638,9 +615,7 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
data->serial = serial; data->serial = serial;
data->irp = irp; data->irp = irp;
/* data freed by irp_thread_func */ /* data freed by irp_thread_func */
irpThread = CreateThread(NULL, irpThread = CreateThread(NULL,
0, 0,
(LPTHREAD_START_ROUTINE)irp_thread_func, (LPTHREAD_START_ROUTINE)irp_thread_func,
@ -654,8 +629,8 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
goto error_handle; goto error_handle;
} }
key = irp->CompletionId; key = irp->CompletionId;
if (!ListDictionary_Add(serial->IrpThreads, (void*)key, irpThread)) if (!ListDictionary_Add(serial->IrpThreads, (void*)key, irpThread))
{ {
WLog_ERR(TAG, "ListDictionary_Add failed!"); WLog_ERR(TAG, "ListDictionary_Add failed!");
@ -663,43 +638,36 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
} }
return; return;
error_handle:
error_handle:
irp->IoStatus = STATUS_NO_MEMORY; irp->IoStatus = STATUS_NO_MEMORY;
irp->Complete(irp); irp->Complete(irp);
free(data); free(data);
} }
static void terminate_pending_irp_threads(SERIAL_DEVICE *serial) static void terminate_pending_irp_threads(SERIAL_DEVICE* serial)
{ {
ULONG_PTR *ids; ULONG_PTR* ids;
int i, nbIds; int i, nbIds;
nbIds = ListDictionary_GetKeys(serial->IrpThreads, &ids); nbIds = ListDictionary_GetKeys(serial->IrpThreads, &ids);
WLog_Print(serial->log, WLOG_DEBUG, "Terminating %d IRP thread(s)", nbIds); WLog_Print(serial->log, WLOG_DEBUG, "Terminating %d IRP thread(s)", nbIds);
for (i=0; i<nbIds; i++) for (i = 0; i < nbIds; i++)
{ {
HANDLE irpThread; HANDLE irpThread;
ULONG_PTR id = ids[i]; ULONG_PTR id = ids[i];
irpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)id); irpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)id);
TerminateThread(irpThread, 0); TerminateThread(irpThread, 0);
if (WaitForSingleObject(irpThread, INFINITE) == WAIT_FAILED) if (WaitForSingleObject(irpThread, INFINITE) == WAIT_FAILED)
{ {
WLog_ERR(TAG,"WaitForSingleObject failed!"); WLog_ERR(TAG, "WaitForSingleObject failed!");
continue; continue;
} }
CloseHandle(irpThread); CloseHandle(irpThread);
WLog_Print(serial->log, WLOG_DEBUG, "IRP thread terminated, CompletionId %d",
WLog_Print(serial->log, WLOG_DEBUG, "IRP thread terminated, CompletionId %d", id); id);
} }
ListDictionary_Clear(serial->IrpThreads); ListDictionary_Clear(serial->IrpThreads);
@ -712,8 +680,8 @@ static void* serial_thread_func(void* arg)
wMessage message; wMessage message;
SERIAL_DEVICE* serial = (SERIAL_DEVICE*) arg; SERIAL_DEVICE* serial = (SERIAL_DEVICE*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(serial->rdpcontext); freerdp_channel_init_thread_context(serial->rdpcontext);
while (1) while (1)
{ {
if (!MessageQueue_Wait(serial->MainIrpQueue)) if (!MessageQueue_Wait(serial->MainIrpQueue))
@ -743,7 +711,8 @@ static void* serial_thread_func(void* arg)
} }
if (error && serial->rdpcontext) if (error && serial->rdpcontext)
setChannelError(serial->rdpcontext, error, "serial_thread_func reported an error"); setChannelError(serial->rdpcontext, error,
"serial_thread_func reported an error");
ExitThread((DWORD) error); ExitThread((DWORD) error);
return NULL; return NULL;
@ -758,7 +727,6 @@ static void* serial_thread_func(void* arg)
static UINT serial_irp_request(DEVICE* device, IRP* irp) static UINT serial_irp_request(DEVICE* device, IRP* irp)
{ {
SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device; SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device;
assert(irp != NULL); assert(irp != NULL);
if (irp == NULL) if (irp == NULL)
@ -774,6 +742,7 @@ static UINT serial_irp_request(DEVICE* device, IRP* irp)
WLog_ERR(TAG, "MessageQueue_Post failed!"); WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -787,16 +756,16 @@ static UINT serial_free(DEVICE* device)
{ {
UINT error; UINT error;
SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device; SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device;
WLog_Print(serial->log, WLOG_DEBUG, "freeing"); WLog_Print(serial->log, WLOG_DEBUG, "freeing");
MessageQueue_PostQuit(serial->MainIrpQueue, 0); MessageQueue_PostQuit(serial->MainIrpQueue, 0);
if (WaitForSingleObject(serial->MainThread, INFINITE) == WAIT_FAILED) if (WaitForSingleObject(serial->MainThread, INFINITE) == WAIT_FAILED)
{ {
error = GetLastError(); error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error; return error;
} }
CloseHandle(serial->MainThread); CloseHandle(serial->MainThread);
if (serial->hComm) if (serial->hComm)
@ -807,7 +776,6 @@ static UINT serial_free(DEVICE* device)
MessageQueue_Free(serial->MainIrpQueue); MessageQueue_Free(serial->MainIrpQueue);
ListDictionary_Free(serial->IrpThreads); ListDictionary_Free(serial->IrpThreads);
DeleteCriticalSection(&serial->TerminatingIrpThreadsLock); DeleteCriticalSection(&serial->TerminatingIrpThreadsLock);
free(serial); free(serial);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -836,7 +804,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
SERIAL_DEVICE* serial; SERIAL_DEVICE* serial;
#endif /* __linux__ */ #endif /* __linux__ */
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
device = (RDPDR_SERIAL*) pEntryPoints->device; device = (RDPDR_SERIAL*) pEntryPoints->device;
name = device->Name; name = device->Name;
path = device->Path; path = device->Path;
@ -851,18 +818,14 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
if ((name && name[0]) && (path && path[0])) if ((name && name[0]) && (path && path[0]))
{ {
wLog* log; wLog* log;
WLog_Init(); WLog_Init();
log = WLog_Get("com.freerdp.channel.serial.client"); log = WLog_Get("com.freerdp.channel.serial.client");
WLog_Print(log, WLOG_DEBUG, "initializing"); WLog_Print(log, WLOG_DEBUG, "initializing");
#ifndef __linux__ /* to be removed */ #ifndef __linux__ /* to be removed */
WLog_Print(log, WLOG_WARN,
WLog_Print(log, WLOG_WARN, "Serial ports redirection not supported on this platform."); "Serial ports redirection not supported on this platform.");
return CHANNEL_RC_INITIALIZATION_ERROR; return CHANNEL_RC_INITIALIZATION_ERROR;
#else /* __linux __ */ #else /* __linux __ */
WLog_Print(log, WLOG_DEBUG, "Defining %s as %s", name, path); WLog_Print(log, WLOG_DEBUG, "Defining %s as %s", name, path);
if (!DefineCommDevice(name /* eg: COM1 */, path /* eg: /dev/ttyS0 */)) if (!DefineCommDevice(name /* eg: COM1 */, path /* eg: /dev/ttyS0 */))
@ -872,6 +835,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
} }
serial = (SERIAL_DEVICE*) calloc(1, sizeof(SERIAL_DEVICE)); serial = (SERIAL_DEVICE*) calloc(1, sizeof(SERIAL_DEVICE));
if (!serial) if (!serial)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -879,15 +843,14 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
} }
serial->log = log; serial->log = log;
serial->device.type = RDPDR_DTYP_SERIAL; serial->device.type = RDPDR_DTYP_SERIAL;
serial->device.name = name; serial->device.name = name;
serial->device.IRPRequest = serial_irp_request; serial->device.IRPRequest = serial_irp_request;
serial->device.Free = serial_free; serial->device.Free = serial_free;
serial->rdpcontext = pEntryPoints->rdpcontext; serial->rdpcontext = pEntryPoints->rdpcontext;
len = strlen(name); len = strlen(name);
serial->device.data = Stream_New(NULL, len + 1); serial->device.data = Stream_New(NULL, len + 1);
if (!serial->device.data) if (!serial->device.data)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -909,8 +872,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
else else
{ {
assert(FALSE); assert(FALSE);
WLog_Print(serial->log, WLOG_DEBUG,
WLog_Print(serial->log, WLOG_DEBUG, "Unknown server's serial driver: %s. SerCx2 will be used", driver); "Unknown server's serial driver: %s. SerCx2 will be used", driver);
serial->ServerSerialDriverId = SerialDriverSerialSys; serial->ServerSerialDriverId = SerialDriverSerialSys;
} }
} }
@ -920,7 +883,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
serial->ServerSerialDriverId = SerialDriverSerialSys; serial->ServerSerialDriverId = SerialDriverSerialSys;
} }
if (device->Permissive != NULL) if (device->Permissive != NULL)
{ {
if (_stricmp(device->Permissive, "permissive") == 0) if (_stricmp(device->Permissive, "permissive") == 0)
@ -934,11 +896,11 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
} }
} }
WLog_Print(serial->log, WLOG_DEBUG, "Server's serial driver: %s (id: %d)",
WLog_Print(serial->log, WLOG_DEBUG, "Server's serial driver: %s (id: %d)", driver, serial->ServerSerialDriverId); driver, serial->ServerSerialDriverId);
/* TODO: implement auto detection of the server's serial driver */ /* TODO: implement auto detection of the server's serial driver */
serial->MainIrpQueue = MessageQueue_New(NULL); serial->MainIrpQueue = MessageQueue_New(NULL);
if (!serial->MainIrpQueue) if (!serial->MainIrpQueue)
{ {
WLog_ERR(TAG, "MessageQueue_New failed!"); WLog_ERR(TAG, "MessageQueue_New failed!");
@ -948,16 +910,19 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
/* IrpThreads content only modified by create_irp_thread() */ /* IrpThreads content only modified by create_irp_thread() */
serial->IrpThreads = ListDictionary_New(FALSE); serial->IrpThreads = ListDictionary_New(FALSE);
if(!serial->IrpThreads)
if (!serial->IrpThreads)
{ {
WLog_ERR(TAG, "ListDictionary_New failed!"); WLog_ERR(TAG, "ListDictionary_New failed!");
error = CHANNEL_RC_NO_MEMORY; error = CHANNEL_RC_NO_MEMORY;
goto error_out; goto error_out;
} }
serial->IrpThreadToBeTerminatedCount = 0; serial->IrpThreadToBeTerminatedCount = 0;
InitializeCriticalSection(&serial->TerminatingIrpThreadsLock); InitializeCriticalSection(&serial->TerminatingIrpThreadsLock);
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial))) if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
(DEVICE*) serial)))
{ {
WLog_ERR(TAG, "EntryPoints->RegisterDevice failed with error %lu!", error); WLog_ERR(TAG, "EntryPoints->RegisterDevice failed with error %lu!", error);
goto error_out; goto error_out;
@ -974,6 +939,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
error = ERROR_INTERNAL_ERROR; error = ERROR_INTERNAL_ERROR;
goto error_out; goto error_out;
} }
#endif /* __linux __ */ #endif /* __linux __ */
} }

View File

@ -44,10 +44,8 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
SMARTCARD_DEVICE* smartcard; SMARTCARD_DEVICE* smartcard;
SMARTCARD_OPERATION* operation; SMARTCARD_OPERATION* operation;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
smartcard = pContext->smartcard; smartcard = pContext->smartcard;
freerdp_channel_init_thread_context(smartcard->rdpcontext); freerdp_channel_init_thread_context(smartcard->rdpcontext);
nCount = 0; nCount = 0;
hEvents[nCount++] = MessageQueue_Event(pContext->IrpQueue); hEvents[nCount++] = MessageQueue_Event(pContext->IrpQueue);
@ -80,7 +78,6 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
break; break;
} }
if (message.id == WMQ_QUIT) if (message.id == WMQ_QUIT)
break; break;
@ -90,7 +87,8 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
{ {
if ((status = smartcard_irp_device_control_call(smartcard, operation))) if ((status = smartcard_irp_device_control_call(smartcard, operation)))
{ {
WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu", status); WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu",
status);
break; break;
} }
@ -99,7 +97,6 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
WLog_ERR(TAG, "Queue_Enqueue failed!"); WLog_ERR(TAG, "Queue_Enqueue failed!");
status = ERROR_INTERNAL_ERROR; status = ERROR_INTERNAL_ERROR;
break; break;
} }
free(operation); free(operation);
@ -108,17 +105,19 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
} }
if (status && smartcard->rdpcontext) if (status && smartcard->rdpcontext)
setChannelError(smartcard->rdpcontext, error, "smartcard_context_thread reported an error"); setChannelError(smartcard->rdpcontext, error,
"smartcard_context_thread reported an error");
ExitThread((DWORD)status); ExitThread((DWORD)status);
return NULL; return NULL;
} }
SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTEXT hContext) SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard,
SCARDCONTEXT hContext)
{ {
SMARTCARD_CONTEXT* pContext; SMARTCARD_CONTEXT* pContext;
pContext = (SMARTCARD_CONTEXT*) calloc(1, sizeof(SMARTCARD_CONTEXT)); pContext = (SMARTCARD_CONTEXT*) calloc(1, sizeof(SMARTCARD_CONTEXT));
if (!pContext) if (!pContext)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -127,8 +126,8 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTE
pContext->smartcard = smartcard; pContext->smartcard = smartcard;
pContext->hContext = hContext; pContext->hContext = hContext;
pContext->IrpQueue = MessageQueue_New(NULL); pContext->IrpQueue = MessageQueue_New(NULL);
if (!pContext->IrpQueue) if (!pContext->IrpQueue)
{ {
WLog_ERR(TAG, "MessageQueue_New failed!"); WLog_ERR(TAG, "MessageQueue_New failed!");
@ -138,6 +137,7 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTE
pContext->thread = CreateThread(NULL, 0, pContext->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) smartcard_context_thread, (LPTHREAD_START_ROUTINE) smartcard_context_thread,
pContext, 0, NULL); pContext, 0, NULL);
if (!pContext->thread) if (!pContext->thread)
{ {
WLog_ERR(TAG, "CreateThread failed!"); WLog_ERR(TAG, "CreateThread failed!");
@ -145,7 +145,6 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTE
} }
return pContext; return pContext;
error_thread: error_thread:
MessageQueue_Free(pContext->IrpQueue); MessageQueue_Free(pContext->IrpQueue);
error_irpqueue: error_irpqueue:
@ -160,18 +159,19 @@ void smartcard_context_free(SMARTCARD_CONTEXT* pContext)
/* cancel blocking calls like SCardGetStatusChange */ /* cancel blocking calls like SCardGetStatusChange */
SCardCancel(pContext->hContext); SCardCancel(pContext->hContext);
if (MessageQueue_PostQuit(pContext->IrpQueue, 0) && (WaitForSingleObject(pContext->thread, INFINITE) == WAIT_FAILED))
if (MessageQueue_PostQuit(pContext->IrpQueue, 0)
&& (WaitForSingleObject(pContext->thread, INFINITE) == WAIT_FAILED))
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
CloseHandle(pContext->thread); CloseHandle(pContext->thread);
MessageQueue_Free(pContext->IrpQueue); MessageQueue_Free(pContext->IrpQueue);
free(pContext); free(pContext);
} }
static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) { static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard)
{
int index; int index;
int keyCount; int keyCount;
ULONG_PTR* pKeys; ULONG_PTR* pKeys;
@ -195,7 +195,8 @@ static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) {
for (index = 0; index < keyCount; index++) for (index = 0; index < keyCount; index++)
{ {
pContext = (SMARTCARD_CONTEXT*) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]); pContext = (SMARTCARD_CONTEXT*) ListDictionary_GetItemValue(
smartcard->rgSCardContextList, (void*) pKeys[index]);
if (!pContext) if (!pContext)
continue; continue;
@ -222,7 +223,8 @@ static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) {
for (index = 0; index < keyCount; index++) for (index = 0; index < keyCount; index++)
{ {
pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(smartcard->rgSCardContextList, (void*) pKeys[index]); pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(
smartcard->rgSCardContextList, (void*) pKeys[index]);
if (!pContext) if (!pContext)
continue; continue;
@ -256,19 +258,18 @@ static UINT smartcard_free(DEVICE* device)
{ {
UINT error; UINT error;
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
/** /**
* Calling smartcard_release_all_contexts to unblock all operations waiting for transactions * Calling smartcard_release_all_contexts to unblock all operations waiting for transactions
* to unlock. * to unlock.
*/ */
smartcard_release_all_contexts(smartcard); smartcard_release_all_contexts(smartcard);
/* Stopping all threads and cancelling all IRPs */ /* Stopping all threads and cancelling all IRPs */
if (smartcard->IrpQueue) if (smartcard->IrpQueue)
{ {
if (MessageQueue_PostQuit(smartcard->IrpQueue, 0) && (WaitForSingleObject(smartcard->thread, INFINITE) == WAIT_FAILED)) if (MessageQueue_PostQuit(smartcard->IrpQueue, 0)
&& (WaitForSingleObject(smartcard->thread, INFINITE) == WAIT_FAILED))
{ {
error = GetLastError(); error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
@ -277,7 +278,6 @@ static UINT smartcard_free(DEVICE* device)
MessageQueue_Free(smartcard->IrpQueue); MessageQueue_Free(smartcard->IrpQueue);
smartcard->IrpQueue = NULL; smartcard->IrpQueue = NULL;
CloseHandle(smartcard->thread); CloseHandle(smartcard->thread);
smartcard->thread = NULL; smartcard->thread = NULL;
} }
@ -299,7 +299,6 @@ static UINT smartcard_free(DEVICE* device)
} }
free(device); free(device);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -316,9 +315,7 @@ static UINT smartcard_free(DEVICE* device)
static UINT smartcard_init(DEVICE* device) static UINT smartcard_init(DEVICE* device)
{ {
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
smartcard_release_all_contexts(smartcard); smartcard_release_all_contexts(smartcard);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -330,10 +327,8 @@ static UINT smartcard_init(DEVICE* device)
UINT smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) UINT smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
{ {
void* key; void* key;
key = (void*)(size_t) irp->CompletionId;
key = (void*) (size_t) irp->CompletionId;
ListDictionary_Remove(smartcard->rgOutstandingMessages, key); ListDictionary_Remove(smartcard->rgOutstandingMessages, key);
return irp->Complete(irp); return irp->Complete(irp);
} }
@ -354,8 +349,8 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
BOOL asyncIrp = FALSE; BOOL asyncIrp = FALSE;
SMARTCARD_CONTEXT* pContext = NULL; SMARTCARD_CONTEXT* pContext = NULL;
SMARTCARD_OPERATION* operation = NULL; SMARTCARD_OPERATION* operation = NULL;
key = (void*)(size_t) irp->CompletionId;
key = (void*) (size_t) irp->CompletionId;
if (!ListDictionary_Add(smartcard->rgOutstandingMessages, key, irp)) if (!ListDictionary_Add(smartcard->rgOutstandingMessages, key, irp))
{ {
WLog_ERR(TAG, "ListDictionary_Add failed!"); WLog_ERR(TAG, "ListDictionary_Add failed!");
@ -373,7 +368,6 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
} }
operation->irp = irp; operation->irp = irp;
status = smartcard_irp_device_control_decode(smartcard, operation); status = smartcard_irp_device_control_decode(smartcard, operation);
if (status != SCARD_S_SUCCESS) if (status != SCARD_S_SUCCESS)
@ -460,7 +454,8 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
break; break;
} }
pContext = ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) operation->hContext); pContext = ListDictionary_GetItemValue(smartcard->rgSCardContextList,
(void*) operation->hContext);
if (!pContext) if (!pContext)
asyncIrp = FALSE; asyncIrp = FALSE;
@ -469,14 +464,17 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
{ {
if ((status = smartcard_irp_device_control_call(smartcard, operation))) if ((status = smartcard_irp_device_control_call(smartcard, operation)))
{ {
WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu!", status); WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu!",
status);
return (UINT32)status; return (UINT32)status;
} }
if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp)) if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp))
{ {
WLog_ERR(TAG, "Queue_Enqueue failed!"); WLog_ERR(TAG, "Queue_Enqueue failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
free(operation); free(operation);
} }
else else
@ -493,7 +491,8 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
} }
else else
{ {
WLog_ERR(TAG, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X", WLog_ERR(TAG,
"Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
irp->MajorFunction, irp->MinorFunction); irp->MajorFunction, irp->MinorFunction);
irp->IoStatus = (UINT32)STATUS_NOT_SUPPORTED; irp->IoStatus = (UINT32)STATUS_NOT_SUPPORTED;
@ -503,6 +502,7 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -515,9 +515,7 @@ static void* smartcard_thread_func(void* arg)
wMessage message; wMessage message;
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
freerdp_channel_init_thread_context(smartcard->rdpcontext); freerdp_channel_init_thread_context(smartcard->rdpcontext);
nCount = 0; nCount = 0;
hEvents[nCount++] = MessageQueue_Event(smartcard->IrpQueue); hEvents[nCount++] = MessageQueue_Event(smartcard->IrpQueue);
hEvents[nCount++] = Queue_Event(smartcard->CompletedIrpQueue); hEvents[nCount++] = Queue_Event(smartcard->CompletedIrpQueue);
@ -551,7 +549,6 @@ static void* smartcard_thread_func(void* arg)
break; break;
} }
if (message.id == WMQ_QUIT) if (message.id == WMQ_QUIT)
{ {
while (1) while (1)
@ -621,7 +618,6 @@ static void* smartcard_thread_func(void* arg)
if (status == WAIT_OBJECT_0) if (status == WAIT_OBJECT_0)
{ {
irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue);
if (irp) if (irp)
@ -654,9 +650,12 @@ static void* smartcard_thread_func(void* arg)
} }
} }
} }
out: out:
if (error && smartcard->rdpcontext) if (error && smartcard->rdpcontext)
setChannelError(smartcard->rdpcontext, error, "smartcard_thread_func reported an error"); setChannelError(smartcard->rdpcontext, error,
"smartcard_thread_func reported an error");
ExitThread((DWORD)error); ExitThread((DWORD)error);
return NULL; return NULL;
@ -670,11 +669,13 @@ out:
static UINT smartcard_irp_request(DEVICE* device, IRP* irp) static UINT smartcard_irp_request(DEVICE* device, IRP* irp)
{ {
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
if (!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!"); WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -695,13 +696,11 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
RDPDR_SMARTCARD* device; RDPDR_SMARTCARD* device;
SMARTCARD_DEVICE* smartcard; SMARTCARD_DEVICE* smartcard;
UINT error = CHANNEL_RC_NO_MEMORY; UINT error = CHANNEL_RC_NO_MEMORY;
device = (RDPDR_SMARTCARD*) pEntryPoints->device; device = (RDPDR_SMARTCARD*) pEntryPoints->device;
name = device->Name; name = device->Name;
path = device->Path; path = device->Path;
smartcard = (SMARTCARD_DEVICE*) calloc(1, sizeof(SMARTCARD_DEVICE)); smartcard = (SMARTCARD_DEVICE*) calloc(1, sizeof(SMARTCARD_DEVICE));
if (!smartcard) if (!smartcard)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -714,9 +713,9 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
smartcard->device.Init = smartcard_init; smartcard->device.Init = smartcard_init;
smartcard->device.Free = smartcard_free; smartcard->device.Free = smartcard_free;
smartcard->rdpcontext = pEntryPoints->rdpcontext; smartcard->rdpcontext = pEntryPoints->rdpcontext;
length = strlen(smartcard->device.name); length = strlen(smartcard->device.name);
smartcard->device.data = Stream_New(NULL, length + 1); smartcard->device.data = Stream_New(NULL, length + 1);
if (!smartcard->device.data) if (!smartcard->device.data)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
@ -724,7 +723,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
} }
Stream_Write(smartcard->device.data, "SCARD", 6); Stream_Write(smartcard->device.data, "SCARD", 6);
smartcard->name = NULL; smartcard->name = NULL;
smartcard->path = NULL; smartcard->path = NULL;
@ -742,14 +740,15 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
} }
smartcard->IrpQueue = MessageQueue_New(NULL); smartcard->IrpQueue = MessageQueue_New(NULL);
if (!smartcard->IrpQueue) if (!smartcard->IrpQueue)
{ {
WLog_ERR(TAG, "MessageQueue_New failed!"); WLog_ERR(TAG, "MessageQueue_New failed!");
goto error_irp_queue; goto error_irp_queue;
} }
smartcard->CompletedIrpQueue = Queue_New(TRUE, -1, -1); smartcard->CompletedIrpQueue = Queue_New(TRUE, -1, -1);
if (!smartcard->CompletedIrpQueue) if (!smartcard->CompletedIrpQueue)
{ {
WLog_ERR(TAG, "Queue_New failed!"); WLog_ERR(TAG, "Queue_New failed!");
@ -757,6 +756,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
} }
smartcard->rgSCardContextList = ListDictionary_New(TRUE); smartcard->rgSCardContextList = ListDictionary_New(TRUE);
if (!smartcard->rgSCardContextList) if (!smartcard->rgSCardContextList)
{ {
WLog_ERR(TAG, "ListDictionary_New failed!"); WLog_ERR(TAG, "ListDictionary_New failed!");
@ -765,23 +765,25 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
ListDictionary_ValueObject(smartcard->rgSCardContextList)->fnObjectFree = ListDictionary_ValueObject(smartcard->rgSCardContextList)->fnObjectFree =
(OBJECT_FREE_FN) smartcard_context_free; (OBJECT_FREE_FN) smartcard_context_free;
smartcard->rgOutstandingMessages = ListDictionary_New(TRUE); smartcard->rgOutstandingMessages = ListDictionary_New(TRUE);
if (!smartcard->rgOutstandingMessages) if (!smartcard->rgOutstandingMessages)
{ {
WLog_ERR(TAG, "ListDictionary_New failed!"); WLog_ERR(TAG, "ListDictionary_New failed!");
goto error_outstanding_messages; goto error_outstanding_messages;
} }
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) smartcard))) if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
(DEVICE*) smartcard)))
{ {
WLog_ERR(TAG, "RegisterDevice failed!"); WLog_ERR(TAG, "RegisterDevice failed!");
goto error_outstanding_messages; goto error_outstanding_messages;
} }
smartcard->thread = CreateThread(NULL, 0,
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
smartcard, CREATE_SUSPENDED, NULL); smartcard, CREATE_SUSPENDED, NULL);
if (!smartcard->thread) if (!smartcard->thread)
{ {
WLog_ERR(TAG, "ListDictionary_New failed!"); WLog_ERR(TAG, "ListDictionary_New failed!");
@ -790,9 +792,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
} }
ResumeThread(smartcard->thread); ResumeThread(smartcard->thread);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
error_thread: error_thread:
ListDictionary_Free(smartcard->rgOutstandingMessages); ListDictionary_Free(smartcard->rgOutstandingMessages);
error_outstanding_messages: error_outstanding_messages:

View File

@ -71,10 +71,10 @@ struct _TSMF_PRESENTATION
{ {
BYTE presentation_id[GUID_SIZE]; BYTE presentation_id[GUID_SIZE];
const char *audio_name; const char* audio_name;
const char *audio_device; const char* audio_device;
IWTSVirtualChannelCallback *channel_callback; IWTSVirtualChannelCallback* channel_callback;
UINT64 audio_start_time; UINT64 audio_start_time;
UINT64 audio_end_time; UINT64 audio_end_time;
@ -82,7 +82,7 @@ struct _TSMF_PRESENTATION
UINT32 volume; UINT32 volume;
UINT32 muted; UINT32 muted;
wArrayList *stream_list; wArrayList* stream_list;
int x; int x;
int y; int y;
@ -90,7 +90,7 @@ struct _TSMF_PRESENTATION
int height; int height;
int nr_rects; int nr_rects;
void *rects; void* rects;
}; };
struct _TSMF_STREAM struct _TSMF_STREAM
@ -99,7 +99,7 @@ struct _TSMF_STREAM
TSMF_PRESENTATION* presentation; TSMF_PRESENTATION* presentation;
ITSMFDecoder *decoder; ITSMFDecoder* decoder;
int major_type; int major_type;
int eos; int eos;
@ -109,7 +109,7 @@ struct _TSMF_STREAM
UINT32 width; UINT32 width;
UINT32 height; UINT32 height;
ITSMFAudioDevice *audio; ITSMFAudioDevice* audio;
UINT32 sample_rate; UINT32 sample_rate;
UINT32 channels; UINT32 channels;
UINT32 bits_per_sample; UINT32 bits_per_sample;
@ -130,8 +130,8 @@ struct _TSMF_STREAM
HANDLE stopEvent; HANDLE stopEvent;
HANDLE ready; HANDLE ready;
wQueue *sample_list; wQueue* sample_list;
wQueue *sample_ack_list; wQueue* sample_ack_list;
rdpContext* rdpcontext; rdpContext* rdpcontext;
BOOL seeking; BOOL seeking;
@ -145,18 +145,18 @@ struct _TSMF_SAMPLE
UINT64 duration; UINT64 duration;
UINT32 extensions; UINT32 extensions;
UINT32 data_size; UINT32 data_size;
BYTE *data; BYTE* data;
UINT32 decoded_size; UINT32 decoded_size;
UINT32 pixfmt; UINT32 pixfmt;
BOOL invalidTimestamps; BOOL invalidTimestamps;
TSMF_STREAM* stream; TSMF_STREAM* stream;
IWTSVirtualChannelCallback *channel_callback; IWTSVirtualChannelCallback* channel_callback;
UINT64 ack_time; UINT64 ack_time;
}; };
static wArrayList *presentation_list = NULL; static wArrayList* presentation_list = NULL;
static int TERMINATING = 0; static int TERMINATING = 0;
static void _tsmf_presentation_free(TSMF_PRESENTATION* presentation); static void _tsmf_presentation_free(TSMF_PRESENTATION* presentation);
@ -173,7 +173,7 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
{ {
UINT32 index; UINT32 index;
UINT32 count; UINT32 count;
TSMF_STREAM *s; TSMF_STREAM* s;
TSMF_SAMPLE* sample; TSMF_SAMPLE* sample;
BOOL pending = FALSE; BOOL pending = FALSE;
TSMF_PRESENTATION* presentation = stream->presentation; TSMF_PRESENTATION* presentation = stream->presentation;
@ -203,7 +203,7 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
s = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); s = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
/* Start time is more reliable than end time as some stream types seem to have incorrect /* Start time is more reliable than end time as some stream types seem to have incorrect
* end times from the server * end times from the server
@ -238,20 +238,22 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
if (pending) if (pending)
return NULL; return NULL;
sample = (TSMF_SAMPLE *) Queue_Dequeue(stream->sample_list); sample = (TSMF_SAMPLE*) Queue_Dequeue(stream->sample_list);
/* Only update stream last end time if the sample end time is valid and greater than the current stream end time */ /* Only update stream last end time if the sample end time is valid and greater than the current stream end time */
if (sample && (sample->end_time > stream->last_end_time) && (!sample->invalidTimestamps)) if (sample && (sample->end_time > stream->last_end_time)
&& (!sample->invalidTimestamps))
stream->last_end_time = sample->end_time; stream->last_end_time = sample->end_time;
/* Only update stream last start time if the sample start time is valid and greater than the current stream start time */ /* Only update stream last start time if the sample start time is valid and greater than the current stream start time */
if (sample && (sample->start_time > stream->last_start_time) && (!sample->invalidTimestamps)) if (sample && (sample->start_time > stream->last_start_time)
&& (!sample->invalidTimestamps))
stream->last_start_time = sample->start_time; stream->last_start_time = sample->start_time;
return sample; return sample;
} }
static void tsmf_sample_free(void *arg) static void tsmf_sample_free(void* arg)
{ {
TSMF_SAMPLE* sample = arg; TSMF_SAMPLE* sample = arg;
@ -267,7 +269,8 @@ static BOOL tsmf_sample_ack(TSMF_SAMPLE* sample)
if (!sample) if (!sample)
return FALSE; return FALSE;
return tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size); return tsmf_playback_ack(sample->channel_callback, sample->sample_id,
sample->duration, sample->data_size);
} }
static BOOL tsmf_sample_queue_ack(TSMF_SAMPLE* sample) static BOOL tsmf_sample_queue_ack(TSMF_SAMPLE* sample)
@ -325,6 +328,7 @@ static BOOL tsmf_stream_process_ack(void* arg, BOOL force)
dequeue: dequeue:
sample = Queue_Dequeue(stream->sample_ack_list); sample = Queue_Dequeue(stream->sample_ack_list);
if (sample) if (sample)
{ {
tsmf_sample_ack(sample); tsmf_sample_ack(sample);
@ -336,7 +340,8 @@ finally:
return rc; return rc;
} }
TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCallback* pChannelCallback) TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid,
IWTSVirtualChannelCallback* pChannelCallback)
{ {
TSMF_PRESENTATION* presentation; TSMF_PRESENTATION* presentation;
@ -344,6 +349,7 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCal
return NULL; return NULL;
presentation = (TSMF_PRESENTATION*) calloc(1, sizeof(TSMF_PRESENTATION)); presentation = (TSMF_PRESENTATION*) calloc(1, sizeof(TSMF_PRESENTATION));
if (!presentation) if (!presentation)
{ {
WLog_ERR(TAG, "calloc failed"); WLog_ERR(TAG, "calloc failed");
@ -354,22 +360,22 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCal
presentation->channel_callback = pChannelCallback; presentation->channel_callback = pChannelCallback;
presentation->volume = 5000; /* 50% */ presentation->volume = 5000; /* 50% */
presentation->muted = 0; presentation->muted = 0;
if (!(presentation->stream_list = ArrayList_New(TRUE))) if (!(presentation->stream_list = ArrayList_New(TRUE)))
goto error_stream_list; goto error_stream_list;
ArrayList_Object(presentation->stream_list)->fnObjectFree = (OBJECT_FREE_FN) _tsmf_stream_free; ArrayList_Object(presentation->stream_list)->fnObjectFree =
(OBJECT_FREE_FN) _tsmf_stream_free;
if (ArrayList_Add(presentation_list, presentation) < 0) if (ArrayList_Add(presentation_list, presentation) < 0)
goto error_add; goto error_add;
return presentation; return presentation;
error_add: error_add:
ArrayList_Free(presentation->stream_list); ArrayList_Free(presentation->stream_list);
error_stream_list: error_stream_list:
free(presentation); free(presentation);
return NULL; return NULL;
} }
static char* guid_to_string(const BYTE* guid, char* str, size_t len) static char* guid_to_string(const BYTE* guid, char* str, size_t len)
@ -379,20 +385,19 @@ static char* guid_to_string(const BYTE* guid, char* str, size_t len)
if (!guid || !str) if (!guid || !str)
return NULL; return NULL;
for (i=0; i<GUID_SIZE && len > 2*i; i++) for (i = 0; i < GUID_SIZE && len > 2 * i; i++)
sprintf_s(str + (2*i), len - 2*i, "%02X", guid[i]); sprintf_s(str + (2 * i), len - 2 * i, "%02X", guid[i]);
return str; return str;
} }
TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE *guid) TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE* guid)
{ {
UINT32 index; UINT32 index;
UINT32 count; UINT32 count;
BOOL found = FALSE; BOOL found = FALSE;
char guid_str[GUID_SIZE * 2 + 1]; char guid_str[GUID_SIZE * 2 + 1];
TSMF_PRESENTATION* presentation; TSMF_PRESENTATION* presentation;
ArrayList_Lock(presentation_list); ArrayList_Lock(presentation_list);
count = ArrayList_Count(presentation_list); count = ArrayList_Count(presentation_list);
@ -410,7 +415,8 @@ TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE *guid)
ArrayList_Unlock(presentation_list); ArrayList_Unlock(presentation_list);
if (!found) if (!found)
WLog_WARN(TAG, "presentation id %s not found", guid_to_string(guid, guid_str, sizeof(guid_str))); WLog_WARN(TAG, "presentation id %s not found", guid_to_string(guid, guid_str,
sizeof(guid_str)));
return (found) ? presentation : NULL; return (found) ? presentation : NULL;
} }
@ -421,9 +427,9 @@ static BOOL tsmf_sample_playback_video(TSMF_SAMPLE* sample)
TSMF_VIDEO_FRAME_EVENT event; TSMF_VIDEO_FRAME_EVENT event;
TSMF_STREAM* stream = sample->stream; TSMF_STREAM* stream = sample->stream;
TSMF_PRESENTATION* presentation = stream->presentation; TSMF_PRESENTATION* presentation = stream->presentation;
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) sample->channel_callback; TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*)
sample->channel_callback;
TsmfClientContext* tsmf = (TsmfClientContext*) callback->plugin->pInterface; TsmfClientContext* tsmf = (TsmfClientContext*) callback->plugin->pInterface;
DEBUG_TSMF("MessageId %d EndTime %d data_size %d consumed.", DEBUG_TSMF("MessageId %d EndTime %d data_size %d consumed.",
sample->sample_id, (int) sample->end_time, sample->data_size); sample->sample_id, (int) sample->end_time, sample->data_size);
@ -436,34 +442,33 @@ static BOOL tsmf_sample_playback_video(TSMF_SAMPLE* sample)
*/ */
if (stream->next_start_time > t && if (stream->next_start_time > t &&
((sample->start_time >= presentation->audio_start_time) || ((sample->start_time >= presentation->audio_start_time) ||
((sample->start_time < stream->last_start_time) && (!sample->invalidTimestamps)))) ((sample->start_time < stream->last_start_time)
&& (!sample->invalidTimestamps))))
{ {
USleep((stream->next_start_time - t) / 10); USleep((stream->next_start_time - t) / 10);
} }
stream->next_start_time = t + sample->duration - 50000; stream->next_start_time = t + sample->duration - 50000;
ZeroMemory(&event, sizeof(TSMF_VIDEO_FRAME_EVENT)); ZeroMemory(&event, sizeof(TSMF_VIDEO_FRAME_EVENT));
event.frameData = sample->data; event.frameData = sample->data;
event.frameSize = sample->decoded_size; event.frameSize = sample->decoded_size;
event.framePixFmt = sample->pixfmt; event.framePixFmt = sample->pixfmt;
event.frameWidth = sample->stream->width; event.frameWidth = sample->stream->width;
event.frameHeight = sample->stream->height; event.frameHeight = sample->stream->height;
#if 0 #if 0
/* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we /* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we
extract the Y values to create a grayscale image. */ extract the Y values to create a grayscale image. */
static int frame_id = 0; static int frame_id = 0;
char buf[100]; char buf[100];
FILE *fp; FILE* fp;
if ((frame_id % 30) == 0) if ((frame_id % 30) == 0)
{ {
sprintf_s(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id); sprintf_s(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id);
fp = fopen(buf, "wb"); fp = fopen(buf, "wb");
fwrite("P5\n", 1, 3, fp); fwrite("P5\n", 1, 3, fp);
sprintf_s(buf, sizeof(buf), "%d %d\n", sample->stream->width, sample->stream->height); sprintf_s(buf, sizeof(buf), "%d %d\n", sample->stream->width,
sample->stream->height);
fwrite(buf, 1, strlen(buf), fp); fwrite(buf, 1, strlen(buf), fp);
fwrite("255\n", 1, 4, fp); fwrite("255\n", 1, 4, fp);
fwrite(sample->data, 1, sample->stream->width * sample->stream->height, fp); fwrite(sample->data, 1, sample->stream->width * sample->stream->height, fp);
@ -473,7 +478,6 @@ static BOOL tsmf_sample_playback_video(TSMF_SAMPLE* sample)
frame_id++; frame_id++;
#endif #endif
/* The frame data ownership is passed to the event object, and is freed after the event is processed. */ /* The frame data ownership is passed to the event object, and is freed after the event is processed. */
sample->data = NULL; sample->data = NULL;
sample->decoded_size = 0; sample->decoded_size = 0;
@ -483,6 +487,7 @@ static BOOL tsmf_sample_playback_video(TSMF_SAMPLE* sample)
free(event.frameData); free(event.frameData);
} }
return TRUE; return TRUE;
} }
@ -491,13 +496,13 @@ static BOOL tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
UINT64 latency = 0; UINT64 latency = 0;
TSMF_STREAM* stream = sample->stream; TSMF_STREAM* stream = sample->stream;
BOOL ret; BOOL ret;
DEBUG_TSMF("MessageId %d EndTime %d consumed.", DEBUG_TSMF("MessageId %d EndTime %d consumed.",
sample->sample_id, (int)sample->end_time); sample->sample_id, (int)sample->end_time);
if (stream->audio && sample->data) if (stream->audio && sample->data)
{ {
ret = sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size); ret = sample->stream->audio->Play(sample->stream->audio, sample->data,
sample->decoded_size);
sample->data = NULL; sample->data = NULL;
sample->decoded_size = 0; sample->decoded_size = 0;
@ -520,6 +525,7 @@ static BOOL tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
stream->presentation->audio_start_time = sample->start_time + latency; stream->presentation->audio_start_time = sample->start_time + latency;
stream->presentation->audio_end_time = sample->end_time + latency; stream->presentation->audio_end_time = sample->end_time + latency;
} }
return ret; return ret;
} }
@ -546,15 +552,18 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
int count = ArrayList_Count(presentation->stream_list); int count = ArrayList_Count(presentation->stream_list);
int index = 0; int index = 0;
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
UINT64 time_diff; UINT64 time_diff;
temp_stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list,
index);
temp_stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
if (temp_stream->major_type == TSMF_MAJOR_TYPE_AUDIO) if (temp_stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
{ {
UINT64 video_time = (UINT64) stream->decoder->GetRunningTime(stream->decoder); UINT64 video_time = (UINT64) stream->decoder->GetRunningTime(stream->decoder);
UINT64 audio_time = (UINT64) temp_stream->decoder->GetRunningTime(temp_stream->decoder); UINT64 audio_time = (UINT64) temp_stream->decoder->GetRunningTime(
temp_stream->decoder);
UINT64 max_adjust = VIDEO_ADJUST_MAX; UINT64 max_adjust = VIDEO_ADJUST_MAX;
if (video_time < audio_time) if (video_time < audio_time)
@ -568,25 +577,28 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
time_diff = time_diff < VIDEO_ADJUST_MAX ? time_diff : max_adjust; time_diff = time_diff < VIDEO_ADJUST_MAX ? time_diff : max_adjust;
sample->start_time += time_diff; sample->start_time += time_diff;
sample->end_time += time_diff; sample->end_time += time_diff;
break; break;
} }
} }
ArrayList_Unlock(presentation->stream_list); ArrayList_Unlock(presentation->stream_list);
} }
ret = stream->decoder->DecodeEx(stream->decoder, sample->data, sample->data_size, sample->extensions, ret = stream->decoder->DecodeEx(stream->decoder, sample->data,
sample->data_size, sample->extensions,
sample->start_time, sample->end_time, sample->duration); sample->start_time, sample->end_time, sample->duration);
} }
else else
{ {
ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size, sample->extensions); ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size,
sample->extensions);
} }
} }
if (!ret) if (!ret)
{ {
WLog_ERR(TAG, "decode error, queue ack anyways"); WLog_ERR(TAG, "decode error, queue ack anyways");
if (!tsmf_sample_queue_ack(sample)) if (!tsmf_sample_queue_ack(sample))
{ {
WLog_ERR(TAG, "error queuing sample for ack"); WLog_ERR(TAG, "error queuing sample for ack");
@ -605,13 +617,15 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
{ {
pixfmt = stream->decoder->GetDecodedFormat(stream->decoder); pixfmt = stream->decoder->GetDecodedFormat(stream->decoder);
if (pixfmt == ((UINT32) -1)) if (pixfmt == ((UINT32) - 1))
{ {
WLog_ERR(TAG, "unable to decode video format"); WLog_ERR(TAG, "unable to decode video format");
if (!tsmf_sample_queue_ack(sample)) if (!tsmf_sample_queue_ack(sample))
{ {
WLog_ERR(TAG, "error queuing sample for ack"); WLog_ERR(TAG, "error queuing sample for ack");
} }
return FALSE; return FALSE;
} }
@ -633,7 +647,8 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
if (stream->decoder->GetDecodedData) if (stream->decoder->GetDecodedData)
{ {
sample->data = stream->decoder->GetDecodedData(stream->decoder, &sample->decoded_size); sample->data = stream->decoder->GetDecodedData(stream->decoder,
&sample->decoded_size);
switch (sample->stream->major_type) switch (sample->stream->major_type)
{ {
@ -663,11 +678,13 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
if (buffer_filled) if (buffer_filled)
{ {
ack_anticipation_time += (sample->duration/2 < MAX_ACK_TIME) ? sample->duration/2 : MAX_ACK_TIME; ack_anticipation_time += (sample->duration / 2 < MAX_ACK_TIME) ?
sample->duration / 2 : MAX_ACK_TIME;
} }
else else
{ {
ack_anticipation_time += (sample->duration/2 < MAX_ACK_TIME) ? sample->duration/2 : MAX_ACK_TIME; ack_anticipation_time += (sample->duration / 2 < MAX_ACK_TIME) ?
sample->duration / 2 : MAX_ACK_TIME;
} }
switch (sample->stream->major_type) switch (sample->stream->major_type)
@ -684,6 +701,7 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
} }
sample->ack_time = ack_anticipation_time; sample->ack_time = ack_anticipation_time;
if (!tsmf_sample_queue_ack(sample)) if (!tsmf_sample_queue_ack(sample))
{ {
WLog_ERR(TAG, "error queuing sample for ack"); WLog_ERR(TAG, "error queuing sample for ack");
@ -694,13 +712,12 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
return ret; return ret;
} }
static void* tsmf_stream_ack_func(void *arg) static void* tsmf_stream_ack_func(void* arg)
{ {
HANDLE hdl[2]; HANDLE hdl[2];
TSMF_STREAM* stream = (TSMF_STREAM*) arg; TSMF_STREAM* stream = (TSMF_STREAM*) arg;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
DEBUG_TSMF("in %d", stream->stream_id); DEBUG_TSMF("in %d", stream->stream_id);
freerdp_channel_init_thread_context(stream->rdpcontext); freerdp_channel_init_thread_context(stream->rdpcontext);
hdl[0] = stream->stopEvent; hdl[0] = stream->stopEvent;
hdl[1] = Queue_Event(stream->sample_ack_list); hdl[1] = Queue_Event(stream->sample_ack_list);
@ -722,9 +739,11 @@ static void* tsmf_stream_ack_func(void *arg)
if (stream->eos) if (stream->eos)
{ {
while ((stream->currentBufferLevel > 0) || !(tsmf_stream_process_ack(stream, TRUE))) while ((stream->currentBufferLevel > 0)
|| !(tsmf_stream_process_ack(stream, TRUE)))
{ {
DEBUG_TSMF("END OF STREAM PROCESSING!"); DEBUG_TSMF("END OF STREAM PROCESSING!");
if (stream->decoder->BufferLevel) if (stream->decoder->BufferLevel)
stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder); stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder);
else else
@ -750,12 +769,15 @@ static void* tsmf_stream_ack_func(void *arg)
if (ev == WAIT_OBJECT_0) if (ev == WAIT_OBJECT_0)
{ {
DEBUG_TSMF("ack: Stream stopped!"); DEBUG_TSMF("ack: Stream stopped!");
while(1)
while (1)
{ {
if (tsmf_stream_process_ack(stream, TRUE)) if (tsmf_stream_process_ack(stream, TRUE))
break; break;
USleep(1000); USleep(1000);
} }
break; break;
} }
@ -767,24 +789,23 @@ static void* tsmf_stream_ack_func(void *arg)
} }
if (error && stream->rdpcontext) if (error && stream->rdpcontext)
setChannelError(stream->rdpcontext, error, "tsmf_stream_ack_func reported an error"); setChannelError(stream->rdpcontext, error,
"tsmf_stream_ack_func reported an error");
DEBUG_TSMF("out %d", stream->stream_id); DEBUG_TSMF("out %d", stream->stream_id);
ExitThread(0); ExitThread(0);
return NULL; return NULL;
} }
static void* tsmf_stream_playback_func(void *arg) static void* tsmf_stream_playback_func(void* arg)
{ {
HANDLE hdl[2]; HANDLE hdl[2];
TSMF_SAMPLE* sample = NULL; TSMF_SAMPLE* sample = NULL;
TSMF_STREAM* stream = (TSMF_STREAM *) arg; TSMF_STREAM* stream = (TSMF_STREAM*) arg;
TSMF_PRESENTATION* presentation = stream->presentation; TSMF_PRESENTATION* presentation = stream->presentation;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
DWORD status; DWORD status;
DEBUG_TSMF("in %d", stream->stream_id); DEBUG_TSMF("in %d", stream->stream_id);
freerdp_channel_init_thread_context(stream->rdpcontext); freerdp_channel_init_thread_context(stream->rdpcontext);
if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO && if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO &&
@ -795,12 +816,15 @@ static void* tsmf_stream_playback_func(void *arg)
if (stream->decoder->GetDecodedData) if (stream->decoder->GetDecodedData)
{ {
stream->audio = tsmf_load_audio_device( stream->audio = tsmf_load_audio_device(
presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL, presentation->audio_name
presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL); && presentation->audio_name[0] ? presentation->audio_name : NULL,
presentation->audio_device
&& presentation->audio_device[0] ? presentation->audio_device : NULL);
if (stream->audio) if (stream->audio)
{ {
stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels, stream->bits_per_sample); stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels,
stream->bits_per_sample);
} }
} }
} }
@ -849,7 +873,6 @@ static void* tsmf_stream_playback_func(void *arg)
USleep(1000); USleep(1000);
} }
if (stream->audio) if (stream->audio)
{ {
stream->audio->Free(stream->audio); stream->audio->Free(stream->audio);
@ -857,7 +880,8 @@ static void* tsmf_stream_playback_func(void *arg)
} }
if (error && stream->rdpcontext) if (error && stream->rdpcontext)
setChannelError(stream->rdpcontext, error, "tsmf_stream_playback_func reported an error"); setChannelError(stream->rdpcontext, error,
"tsmf_stream_playback_func reported an error");
DEBUG_TSMF("out %d", stream->stream_id); DEBUG_TSMF("out %d", stream->stream_id);
ExitThread(0); ExitThread(0);
@ -866,11 +890,11 @@ static void* tsmf_stream_playback_func(void *arg)
static BOOL tsmf_stream_start(TSMF_STREAM* stream) static BOOL tsmf_stream_start(TSMF_STREAM* stream)
{ {
if (!stream || !stream->presentation || !stream->decoder || !stream->decoder->Control) if (!stream || !stream->presentation || !stream->decoder
|| !stream->decoder->Control)
return TRUE; return TRUE;
stream->eos = 0; stream->eos = 0;
return stream->decoder->Control(stream->decoder, Control_Restart, NULL); return stream->decoder->Control(stream->decoder, Control_Restart, NULL);
} }
@ -894,7 +918,6 @@ static BOOL tsmf_stream_stop(TSMF_STREAM* stream)
{ {
DEBUG_TSMF("Stop with no pending eos response, so do it immediately."); DEBUG_TSMF("Stop with no pending eos response, so do it immediately.");
tsmf_stream_flush(stream); tsmf_stream_flush(stream);
return stream->decoder->Control(stream->decoder, Control_Stop, NULL); return stream->decoder->Control(stream->decoder, Control_Stop, NULL);
} }
} }
@ -913,11 +936,11 @@ static BOOL tsmf_stream_restart(TSMF_STREAM* stream)
return TRUE; return TRUE;
stream->eos = 0; stream->eos = 0;
return stream->decoder->Control(stream->decoder, Control_Restart, NULL); return stream->decoder->Control(stream->decoder, Control_Restart, NULL);
} }
static BOOL tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UINT32 muted) static BOOL tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume,
UINT32 muted)
{ {
if (!stream || !stream->decoder) if (!stream || !stream->decoder)
return TRUE; return TRUE;
@ -930,25 +953,25 @@ static BOOL tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UIN
{ {
return stream->audio->ChangeVolume(stream->audio, newVolume, muted); return stream->audio->ChangeVolume(stream->audio, newVolume, muted);
} }
return TRUE; return TRUE;
} }
BOOL tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume, UINT32 muted) BOOL tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation,
UINT32 newVolume, UINT32 muted)
{ {
UINT32 index; UINT32 index;
UINT32 count; UINT32 count;
TSMF_STREAM* stream; TSMF_STREAM* stream;
BOOL ret = TRUE; BOOL ret = TRUE;
presentation->volume = newVolume; presentation->volume = newVolume;
presentation->muted = muted; presentation->muted = muted;
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list); count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
ret &= tsmf_stream_change_volume(stream, newVolume, muted); ret &= tsmf_stream_change_volume(stream, newVolume, muted);
} }
@ -962,13 +985,12 @@ BOOL tsmf_presentation_paused(TSMF_PRESENTATION* presentation)
UINT32 count; UINT32 count;
TSMF_STREAM* stream; TSMF_STREAM* stream;
BOOL ret = TRUE; BOOL ret = TRUE;
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list); count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
ret &= tsmf_stream_pause(stream); ret &= tsmf_stream_pause(stream);
} }
@ -982,13 +1004,12 @@ BOOL tsmf_presentation_restarted(TSMF_PRESENTATION* presentation)
UINT32 count; UINT32 count;
TSMF_STREAM* stream; TSMF_STREAM* stream;
BOOL ret = TRUE; BOOL ret = TRUE;
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list); count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
ret &= tsmf_stream_restart(stream); ret &= tsmf_stream_restart(stream);
} }
@ -1002,13 +1023,12 @@ BOOL tsmf_presentation_start(TSMF_PRESENTATION* presentation)
UINT32 count; UINT32 count;
TSMF_STREAM* stream; TSMF_STREAM* stream;
BOOL ret = TRUE; BOOL ret = TRUE;
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list); count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
ret &= tsmf_stream_start(stream); ret &= tsmf_stream_start(stream);
} }
@ -1026,13 +1046,14 @@ UINT tsmf_presentation_sync(TSMF_PRESENTATION* presentation)
UINT32 index; UINT32 index;
UINT32 count; UINT32 count;
UINT error; UINT error;
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list); count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
TSMF_STREAM* stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); TSMF_STREAM* stream = (TSMF_STREAM*) ArrayList_GetItem(
presentation->stream_list, index);
if (WaitForSingleObject(stream->ready, 500) == WAIT_FAILED) if (WaitForSingleObject(stream->ready, 500) == WAIT_FAILED)
{ {
error = GetLastError(); error = GetLastError();
@ -1051,30 +1072,28 @@ BOOL tsmf_presentation_stop(TSMF_PRESENTATION* presentation)
UINT32 count; UINT32 count;
TSMF_STREAM* stream; TSMF_STREAM* stream;
BOOL ret = TRUE; BOOL ret = TRUE;
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list); count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
ret &= tsmf_stream_stop(stream); ret &= tsmf_stream_stop(stream);
} }
ArrayList_Unlock(presentation->stream_list); ArrayList_Unlock(presentation->stream_list);
presentation->audio_start_time = 0; presentation->audio_start_time = 0;
presentation->audio_end_time = 0; presentation->audio_end_time = 0;
return ret; return ret;
} }
BOOL tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, BOOL tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
UINT32 x, UINT32 y, UINT32 width, UINT32 height, int num_rects, RDP_RECT *rects) UINT32 x, UINT32 y, UINT32 width, UINT32 height, int num_rects, RDP_RECT* rects)
{ {
UINT32 index; UINT32 index;
UINT32 count; UINT32 count;
TSMF_STREAM* stream; TSMF_STREAM* stream;
void *tmp_rects = NULL; void* tmp_rects = NULL;
BOOL ret = TRUE; BOOL ret = TRUE;
/* The server may send messages with invalid width / height. /* The server may send messages with invalid width / height.
@ -1086,32 +1105,28 @@ BOOL tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
* added to the presentation. Also, num_rects is used to indicate whether or not the window is visible. * added to the presentation. Also, num_rects is used to indicate whether or not the window is visible.
* So, always process a valid message with unchanged position/size and/or no visibility rects. * So, always process a valid message with unchanged position/size and/or no visibility rects.
*/ */
presentation->x = x; presentation->x = x;
presentation->y = y; presentation->y = y;
presentation->width = width; presentation->width = width;
presentation->height = height; presentation->height = height;
tmp_rects = realloc(presentation->rects, sizeof(RDP_RECT) * num_rects); tmp_rects = realloc(presentation->rects, sizeof(RDP_RECT) * num_rects);
presentation->nr_rects = num_rects; presentation->nr_rects = num_rects;
presentation->rects = tmp_rects; presentation->rects = tmp_rects;
CopyMemory(presentation->rects, rects, sizeof(RDP_RECT) * num_rects); CopyMemory(presentation->rects, rects, sizeof(RDP_RECT) * num_rects);
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list); count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
if (!stream->decoder) if (!stream->decoder)
continue; continue;
if (stream->decoder->UpdateRenderingArea) if (stream->decoder->UpdateRenderingArea)
{ {
ret = stream->decoder->UpdateRenderingArea(stream->decoder, x, y, width, height, num_rects, rects); ret = stream->decoder->UpdateRenderingArea(stream->decoder, x, y, width, height,
num_rects, rects);
} }
} }
@ -1119,7 +1134,8 @@ BOOL tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
return ret; return ret;
} }
void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char *name, const char *device) void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation,
const char* name, const char* device)
{ {
presentation->audio_name = name; presentation->audio_name = name;
presentation->audio_device = device; presentation->audio_device = device;
@ -1146,6 +1162,7 @@ BOOL tsmf_stream_flush(TSMF_STREAM* stream)
stream->presentation->audio_start_time = 0; stream->presentation->audio_start_time = 0;
stream->presentation->audio_end_time = 0; stream->presentation->audio_end_time = 0;
} }
return TRUE; return TRUE;
} }
@ -1154,9 +1171,7 @@ void _tsmf_presentation_free(TSMF_PRESENTATION* presentation)
tsmf_presentation_stop(presentation); tsmf_presentation_stop(presentation);
ArrayList_Clear(presentation->stream_list); ArrayList_Clear(presentation->stream_list);
ArrayList_Free(presentation->stream_list); ArrayList_Free(presentation->stream_list);
free(presentation->rects); free(presentation->rects);
ZeroMemory(presentation, sizeof(TSMF_PRESENTATION)); ZeroMemory(presentation, sizeof(TSMF_PRESENTATION));
free(presentation); free(presentation);
} }
@ -1166,7 +1181,8 @@ void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
ArrayList_Remove(presentation_list, presentation); ArrayList_Remove(presentation_list, presentation);
} }
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id, rdpContext* rdpcontext) TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
rdpContext* rdpcontext)
{ {
TSMF_STREAM* stream; TSMF_STREAM* stream;
stream = tsmf_stream_find_by_id(presentation, stream_id); stream = tsmf_stream_find_by_id(presentation, stream_id);
@ -1178,6 +1194,7 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
} }
stream = (TSMF_STREAM*) calloc(1, sizeof(TSMF_STREAM)); stream = (TSMF_STREAM*) calloc(1, sizeof(TSMF_STREAM));
if (!stream) if (!stream)
{ {
WLog_ERR(TAG, "Calloc failed"); WLog_ERR(TAG, "Calloc failed");
@ -1187,7 +1204,6 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL; stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL;
stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL; stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL;
stream->currentBufferLevel = 1; stream->currentBufferLevel = 1;
stream->seeking = FALSE; stream->seeking = FALSE;
stream->eos = 0; stream->eos = 0;
stream->eos_message_id = 0; stream->eos_message_id = 0;
@ -1195,24 +1211,36 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
stream->stream_id = stream_id; stream->stream_id = stream_id;
stream->presentation = presentation; stream->presentation = presentation;
stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!stream->stopEvent) if (!stream->stopEvent)
goto error_stopEvent; goto error_stopEvent;
stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL); stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL);
if (!stream->ready) if (!stream->ready)
goto error_ready; goto error_ready;
stream->sample_list = Queue_New(TRUE, -1, -1); stream->sample_list = Queue_New(TRUE, -1, -1);
if (!stream->sample_list) if (!stream->sample_list)
goto error_sample_list; goto error_sample_list;
stream->sample_list->object.fnObjectFree = tsmf_sample_free; stream->sample_list->object.fnObjectFree = tsmf_sample_free;
stream->sample_ack_list = Queue_New(TRUE, -1, -1); stream->sample_ack_list = Queue_New(TRUE, -1, -1);
if (!stream->sample_ack_list) if (!stream->sample_ack_list)
goto error_sample_ack_list; goto error_sample_ack_list;
stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free;
stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, 0, NULL); stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free;
stream->play_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, 0, NULL);
if (!stream->play_thread) if (!stream->play_thread)
goto error_play_thread; goto error_play_thread;
stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL);
stream->ack_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL);
if (!stream->ack_thread) if (!stream->ack_thread)
goto error_ack_thread; goto error_ack_thread;
@ -1220,17 +1248,19 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
goto error_add; goto error_add;
stream->rdpcontext = rdpcontext; stream->rdpcontext = rdpcontext;
return stream; return stream;
error_add: error_add:
SetEvent(stream->stopEvent); SetEvent(stream->stopEvent);
if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED) if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED)
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
error_ack_thread: error_ack_thread:
SetEvent(stream->stopEvent); SetEvent(stream->stopEvent);
if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED) if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED)
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
error_play_thread: error_play_thread:
Queue_Free(stream->sample_ack_list); Queue_Free(stream->sample_ack_list);
error_sample_ack_list: error_sample_ack_list:
@ -1244,13 +1274,13 @@ error_stopEvent:
return NULL; return NULL;
} }
TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stream_id) TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation,
UINT32 stream_id)
{ {
UINT32 index; UINT32 index;
UINT32 count; UINT32 count;
BOOL found = FALSE; BOOL found = FALSE;
TSMF_STREAM* stream; TSMF_STREAM* stream;
ArrayList_Lock(presentation->stream_list); ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list); count = ArrayList_Count(presentation->stream_list);
@ -1269,13 +1299,13 @@ TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stre
return (found) ? stream : NULL; return (found) ? stream : NULL;
} }
static void tsmf_stream_resync(void *arg) static void tsmf_stream_resync(void* arg)
{ {
TSMF_STREAM* stream = arg; TSMF_STREAM* stream = arg;
ResetEvent(stream->ready); ResetEvent(stream->ready);
} }
BOOL tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s) BOOL tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s)
{ {
TS_AM_MEDIA_TYPE mediatype; TS_AM_MEDIA_TYPE mediatype;
BOOL ret = TRUE; BOOL ret = TRUE;
@ -1296,16 +1326,17 @@ BOOL tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s)
{ {
DEBUG_TSMF("video width %d height %d bit_rate %d frame_rate %f codec_data %d", DEBUG_TSMF("video width %d height %d bit_rate %d frame_rate %f codec_data %d",
mediatype.Width, mediatype.Height, mediatype.BitRate, mediatype.Width, mediatype.Height, mediatype.BitRate,
(double) mediatype.SamplesPerSecond.Numerator / (double) mediatype.SamplesPerSecond.Denominator, (double) mediatype.SamplesPerSecond.Numerator / (double)
mediatype.SamplesPerSecond.Denominator,
mediatype.ExtraDataSize); mediatype.ExtraDataSize);
stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL; stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL;
stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL; stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL;
} }
else if (mediatype.MajorType == TSMF_MAJOR_TYPE_AUDIO) else if (mediatype.MajorType == TSMF_MAJOR_TYPE_AUDIO)
{ {
DEBUG_TSMF("audio channel %d sample_rate %d bits_per_sample %d codec_data %d", DEBUG_TSMF("audio channel %d sample_rate %d bits_per_sample %d codec_data %d",
mediatype.Channels, mediatype.SamplesPerSecond.Numerator, mediatype.BitsPerSample, mediatype.Channels, mediatype.SamplesPerSecond.Numerator,
mediatype.BitsPerSample,
mediatype.ExtraDataSize); mediatype.ExtraDataSize);
stream->sample_rate = mediatype.SamplesPerSecond.Numerator; stream->sample_rate = mediatype.SamplesPerSecond.Numerator;
stream->channels = mediatype.Channels; stream->channels = mediatype.Channels;
@ -1322,20 +1353,25 @@ BOOL tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s)
stream->width = mediatype.Width; stream->width = mediatype.Width;
stream->height = mediatype.Height; stream->height = mediatype.Height;
stream->decoder = tsmf_load_decoder(name, &mediatype); stream->decoder = tsmf_load_decoder(name, &mediatype);
ret &= tsmf_stream_change_volume(stream, stream->presentation->volume, stream->presentation->muted); ret &= tsmf_stream_change_volume(stream, stream->presentation->volume,
stream->presentation->muted);
if (!stream->decoder) if (!stream->decoder)
return FALSE; return FALSE;
if (stream->decoder->SetAckFunc) if (stream->decoder->SetAckFunc)
ret &= stream->decoder->SetAckFunc(stream->decoder, tsmf_stream_process_ack, stream); ret &= stream->decoder->SetAckFunc(stream->decoder, tsmf_stream_process_ack,
stream);
if (stream->decoder->SetSyncFunc) if (stream->decoder->SetSyncFunc)
ret &= stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync, stream); ret &= stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync,
stream);
return ret; return ret;
} }
void tsmf_stream_end(TSMF_STREAM* stream, UINT32 message_id, IWTSVirtualChannelCallback* pChannelCallback) void tsmf_stream_end(TSMF_STREAM* stream, UINT32 message_id,
IWTSVirtualChannelCallback* pChannelCallback)
{ {
if (!stream) if (!stream)
return; return;
@ -1372,6 +1408,7 @@ void _tsmf_stream_free(TSMF_STREAM* stream)
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
return; return;
} }
CloseHandle(stream->ack_thread); CloseHandle(stream->ack_thread);
stream->ack_thread = NULL; stream->ack_thread = NULL;
} }
@ -1397,9 +1434,11 @@ void tsmf_stream_free(TSMF_STREAM* stream)
ArrayList_Remove(presentation->stream_list, stream); ArrayList_Remove(presentation->stream_list, stream);
} }
BOOL tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pChannelCallback, BOOL tsmf_stream_push_sample(TSMF_STREAM* stream,
UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions, IWTSVirtualChannelCallback* pChannelCallback,
UINT32 data_size, BYTE *data) UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration,
UINT32 extensions,
UINT32 data_size, BYTE* data)
{ {
TSMF_SAMPLE* sample; TSMF_SAMPLE* sample;
SetEvent(stream->ready); SetEvent(stream->ready);
@ -1408,6 +1447,7 @@ BOOL tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pC
return TRUE; return TRUE;
sample = (TSMF_SAMPLE*) calloc(1, sizeof(TSMF_SAMPLE)); sample = (TSMF_SAMPLE*) calloc(1, sizeof(TSMF_SAMPLE));
if (!sample) if (!sample)
{ {
WLog_ERR(TAG, "calloc sample failed!"); WLog_ERR(TAG, "calloc sample failed!");
@ -1419,10 +1459,12 @@ BOOL tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pC
sample->end_time = end_time; sample->end_time = end_time;
sample->duration = duration; sample->duration = duration;
sample->extensions = extensions; sample->extensions = extensions;
if ((sample->extensions & 0x00000080) || (sample->extensions & 0x00000040)) if ((sample->extensions & 0x00000080) || (sample->extensions & 0x00000040))
sample->invalidTimestamps = TRUE; sample->invalidTimestamps = TRUE;
else else
sample->invalidTimestamps = FALSE; sample->invalidTimestamps = FALSE;
sample->stream = stream; sample->stream = stream;
sample->channel_callback = pChannelCallback; sample->channel_callback = pChannelCallback;
sample->data_size = data_size; sample->data_size = data_size;
@ -1473,9 +1515,13 @@ BOOL tsmf_media_init(void)
if (!presentation_list) if (!presentation_list)
{ {
presentation_list = ArrayList_New(TRUE); presentation_list = ArrayList_New(TRUE);
if (!presentation_list) if (!presentation_list)
return FALSE; return FALSE;
ArrayList_Object(presentation_list)->fnObjectFree = (OBJECT_FREE_FN) _tsmf_presentation_free;
ArrayList_Object(presentation_list)->fnObjectFree = (OBJECT_FREE_FN)
_tsmf_presentation_free;
} }
return TRUE; return TRUE;
} }