Reformatted files touched in last 2 commits.
This commit is contained in:
parent
64590e7e89
commit
9f5da483dc
@ -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;
|
||||||
@ -77,26 +78,29 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand
|
|||||||
if ((error = snd_pcm_hw_params_malloc(&hw_params)) < 0)
|
if ((error = snd_pcm_hw_params_malloc(&hw_params)) < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "snd_pcm_hw_params_malloc (%s)",
|
WLog_ERR(TAG, "snd_pcm_hw_params_malloc (%s)",
|
||||||
snd_strerror(error));
|
snd_strerror(error));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
if ((alsa->actual_rate != alsa->target_rate) ||
|
if ((alsa->actual_rate != alsa->target_rate) ||
|
||||||
(alsa->actual_channels != alsa->target_channels))
|
(alsa->actual_channels != alsa->target_channels))
|
||||||
{
|
{
|
||||||
DEBUG_DVC("actual rate %d / channel %d is "
|
DEBUG_DVC("actual rate %d / channel %d is "
|
||||||
"different from target rate %d / channel %d, resampling required.",
|
"different from target rate %d / channel %d, resampling required.",
|
||||||
alsa->actual_rate, alsa->actual_channels,
|
alsa->actual_rate, alsa->actual_channels,
|
||||||
alsa->target_rate, alsa->target_channels);
|
alsa->target_rate, alsa->target_channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -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;
|
||||||
@ -116,38 +121,37 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
|
|||||||
BYTE* encoded_data;
|
BYTE* encoded_data;
|
||||||
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;
|
||||||
|
|
||||||
if ((alsa->target_rate == alsa->actual_rate) &&
|
if ((alsa->target_rate == alsa->actual_rate) &&
|
||||||
(alsa->target_channels == alsa->actual_channels))
|
(alsa->target_channels == alsa->actual_channels))
|
||||||
{
|
{
|
||||||
frames = size / rbytes_per_frame;
|
frames = size / rbytes_per_frame;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alsa->dsp_context->resample(alsa->dsp_context, src, alsa->bytes_per_channel,
|
alsa->dsp_context->resample(alsa->dsp_context, src, alsa->bytes_per_channel,
|
||||||
alsa->actual_channels, alsa->actual_rate, size / rbytes_per_frame,
|
alsa->actual_channels, alsa->actual_rate, size / rbytes_per_frame,
|
||||||
alsa->target_channels, alsa->target_rate);
|
alsa->target_channels, alsa->target_rate);
|
||||||
frames = alsa->dsp_context->resampled_frames;
|
frames = alsa->dsp_context->resampled_frames;
|
||||||
DEBUG_DVC("resampled %d frames at %d to %d frames at %d",
|
DEBUG_DVC("resampled %d frames at %d to %d frames at %d",
|
||||||
size / rbytes_per_frame, alsa->actual_rate, frames, alsa->target_rate);
|
size / rbytes_per_frame, alsa->actual_rate, frames, alsa->target_rate);
|
||||||
size = frames * tbytes_per_frame;
|
size = frames * tbytes_per_frame;
|
||||||
src = alsa->dsp_context->resampled_buffer;
|
src = alsa->dsp_context->resampled_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (frames > 0)
|
while (frames > 0)
|
||||||
{
|
{
|
||||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
if (status == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
ret = GetLastError();
|
ret = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", ret);
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0)
|
if (status == WAIT_OBJECT_0)
|
||||||
break;
|
break;
|
||||||
@ -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)
|
||||||
@ -166,8 +170,8 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
|
|||||||
if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM)
|
if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM)
|
||||||
{
|
{
|
||||||
if (!alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context,
|
if (!alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context,
|
||||||
alsa->buffer, alsa->buffer_frames * tbytes_per_frame,
|
alsa->buffer, alsa->buffer_frames * tbytes_per_frame,
|
||||||
alsa->target_channels, alsa->block_size))
|
alsa->target_channels, alsa->block_size))
|
||||||
{
|
{
|
||||||
ret = ERROR_INTERNAL_ERROR;
|
ret = ERROR_INTERNAL_ERROR;
|
||||||
break;
|
break;
|
||||||
@ -175,9 +179,8 @@ 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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -185,22 +188,22 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
|
|||||||
encoded_size = alsa->buffer_frames * tbytes_per_frame;
|
encoded_size = alsa->buffer_frames * tbytes_per_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
if (status == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
ret = GetLastError();
|
ret = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", ret);
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0)
|
if (status == WAIT_OBJECT_0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_DVC("encoded %d [%d] to %d [%X]", alsa->buffer_frames,
|
DEBUG_DVC("encoded %d [%d] to %d [%X]", alsa->buffer_frames,
|
||||||
tbytes_per_frame, encoded_size,
|
tbytes_per_frame, encoded_size,
|
||||||
alsa->wformat);
|
alsa->wformat);
|
||||||
ret = alsa->receive(encoded_data, encoded_size, alsa->user_data);
|
ret = alsa->receive(encoded_data, encoded_size, alsa->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,82 +229,85 @@ 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));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!audin_alsa_set_params(alsa, capture_handle))
|
|
||||||
{
|
|
||||||
WLog_ERR(TAG, "audin_alsa_set_params failed");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
WLog_ERR(TAG, "snd_pcm_open (%s)", snd_strerror(error));
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
goto out;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0)
|
if (!audin_alsa_set_params(alsa, capture_handle))
|
||||||
break;
|
|
||||||
|
|
||||||
error = snd_pcm_readi(capture_handle, buffer, alsa->frames_per_packet);
|
|
||||||
|
|
||||||
if (error == -EPIPE)
|
|
||||||
{
|
{
|
||||||
snd_pcm_recover(capture_handle, error, 0);
|
WLog_ERR(TAG, "audin_alsa_set_params failed");
|
||||||
continue;
|
goto out;
|
||||||
}
|
|
||||||
else if (error < 0)
|
|
||||||
{
|
|
||||||
WLog_ERR(TAG, "snd_pcm_readi (%s)", snd_strerror(error));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = audin_alsa_thread_receive(alsa, buffer, error * rbytes_per_frame)))
|
while (1)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "audin_alsa_thread_receive failed with error %lu", error);
|
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (status == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
error = GetLastError();
|
||||||
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == WAIT_OBJECT_0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
error = snd_pcm_readi(capture_handle, buffer, alsa->frames_per_packet);
|
||||||
|
|
||||||
|
if (error == -EPIPE)
|
||||||
|
{
|
||||||
|
snd_pcm_recover(capture_handle, error, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (error < 0)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "snd_pcm_readi (%s)", snd_strerror(error));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = audin_alsa_thread_receive(alsa, buffer, error * rbytes_per_frame)))
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "audin_alsa_thread_receive failed with error %lu", error);
|
||||||
|
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,36 +319,36 @@ 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)
|
||||||
{
|
{
|
||||||
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) &&
|
||||||
(format->nChannels == 1 || format->nChannels == 2))
|
(format->nChannels == 1 || format->nChannels == 2))
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
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))
|
||||||
{
|
{
|
||||||
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:
|
||||||
@ -385,9 +393,9 @@ static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN
|
|||||||
alsa->bytes_per_channel = 2;
|
alsa->bytes_per_channel = 2;
|
||||||
bs = (format->nBlockAlign - 4 * format->nChannels) * 4;
|
bs = (format->nBlockAlign - 4 * format->nChannels) * 4;
|
||||||
alsa->frames_per_packet = (alsa->frames_per_packet * format->nChannels * 2 /
|
alsa->frames_per_packet = (alsa->frames_per_packet * format->nChannels * 2 /
|
||||||
bs + 1) * bs / (format->nChannels * 2);
|
bs + 1) * bs / (format->nChannels * 2);
|
||||||
DEBUG_DVC("aligned FramesPerPacket=%d",
|
DEBUG_DVC("aligned FramesPerPacket=%d",
|
||||||
alsa->frames_per_packet);
|
alsa->frames_per_packet);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
||||||
@ -445,32 +456,30 @@ error_out:
|
|||||||
*/
|
*/
|
||||||
static UINT audin_alsa_close(IAudinDevice* device)
|
static UINT audin_alsa_close(IAudinDevice* device)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
AudinALSADevice* alsa = (AudinALSADevice*) device;
|
AudinALSADevice* alsa = (AudinALSADevice*) 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();
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -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,20 +119,19 @@ 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) ||
|
||||||
(format->nChannels != 1 && format->nChannels != 2))
|
(format->nChannels != 1 && format->nChannels != 2))
|
||||||
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))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -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,44 +302,50 @@ static void* audin_oss_thread_func(void* arg)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Process. */
|
/* Process. */
|
||||||
switch (oss->format.wFormatTag) {
|
switch (oss->format.wFormatTag)
|
||||||
case WAVE_FORMAT_ADPCM:
|
{
|
||||||
if (!oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
|
case WAVE_FORMAT_ADPCM:
|
||||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
|
if (!oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
|
||||||
{
|
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
|
||||||
error = ERROR_INTERNAL_ERROR;
|
{
|
||||||
goto err_out;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
}
|
goto err_out;
|
||||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
}
|
||||||
encoded_size = oss->dsp_context->adpcm_size;
|
|
||||||
break;
|
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||||
case WAVE_FORMAT_DVI_ADPCM:
|
encoded_size = oss->dsp_context->adpcm_size;
|
||||||
if (!oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
|
break;
|
||||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
|
|
||||||
{
|
case WAVE_FORMAT_DVI_ADPCM:
|
||||||
error = ERROR_INTERNAL_ERROR;
|
if (!oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
|
||||||
goto err_out;
|
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
|
||||||
}
|
{
|
||||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
encoded_size = oss->dsp_context->adpcm_size;
|
goto err_out;
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
encoded_data = buffer;
|
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||||
encoded_size = buffer_size;
|
encoded_size = oss->dsp_context->adpcm_size;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
encoded_data = buffer;
|
||||||
|
encoded_size = buffer_size;
|
||||||
|
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,8 +375,9 @@ 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)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
CloseHandle(oss->stopEvent);
|
CloseHandle(oss->stopEvent);
|
||||||
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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,17 +150,18 @@ 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++)
|
||||||
{
|
{
|
||||||
nAvgBytesPerSec = audin->context.server_formats[i].nSamplesPerSec *
|
nAvgBytesPerSec = audin->context.server_formats[i].nSamplesPerSec *
|
||||||
audin->context.server_formats[i].nChannels *
|
audin->context.server_formats[i].nChannels *
|
||||||
audin->context.server_formats[i].wBitsPerSample / 8;
|
audin->context.server_formats[i].wBitsPerSample / 8;
|
||||||
|
|
||||||
if (!Stream_EnsureRemainingCapacity(s, 18))
|
if (!Stream_EnsureRemainingCapacity(s, 18))
|
||||||
{
|
{
|
||||||
@ -178,11 +186,12 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write(s, audin->context.server_formats[i].data,
|
Stream_Write(s, audin->context.server_formats[i].data,
|
||||||
audin->context.server_formats[i].cbSize);
|
audin->context.server_formats[i].cbSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
WLog_ERR(TAG, "context.Opening failed with error %lu", success);
|
if (success)
|
||||||
|
WLog_ERR(TAG, "context.Opening failed with error %lu", success);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,16 +273,17 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s)
|
|||||||
if (audin->context.selected_client_format < 0)
|
if (audin->context.selected_client_format < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "audin->context.selected_client_format = %d",
|
WLog_ERR(TAG, "audin->context.selected_client_format = %d",
|
||||||
audin->context.selected_client_format);
|
audin->context.selected_client_format);
|
||||||
return ERROR_INVALID_DATA;
|
return ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,24 +305,24 @@ 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)
|
||||||
WLog_ERR(TAG, "context.OpenResult failed with error %lu", success);
|
WLog_ERR(TAG, "context.OpenResult failed with error %lu", success);
|
||||||
|
|
||||||
return success;
|
return 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;
|
||||||
@ -327,7 +346,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt
|
|||||||
if (audin->context.selected_client_format < 0)
|
if (audin->context.selected_client_format < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "audin->context.selected_client_format = %d",
|
WLog_ERR(TAG, "audin->context.selected_client_format = %d",
|
||||||
audin->context.selected_client_format);
|
audin->context.selected_client_format);
|
||||||
return ERROR_INVALID_DATA;
|
return ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +355,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt
|
|||||||
if (format->wFormatTag == WAVE_FORMAT_ADPCM)
|
if (format->wFormatTag == WAVE_FORMAT_ADPCM)
|
||||||
{
|
{
|
||||||
audin->dsp_context->decode_ms_adpcm(audin->dsp_context,
|
audin->dsp_context->decode_ms_adpcm(audin->dsp_context,
|
||||||
Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
|
Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
|
||||||
size = audin->dsp_context->adpcm_size;
|
size = audin->dsp_context->adpcm_size;
|
||||||
src = audin->dsp_context->adpcm_buffer;
|
src = audin->dsp_context->adpcm_buffer;
|
||||||
sbytes_per_sample = 2;
|
sbytes_per_sample = 2;
|
||||||
@ -345,7 +364,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt
|
|||||||
else if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
|
else if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
|
||||||
{
|
{
|
||||||
audin->dsp_context->decode_ima_adpcm(audin->dsp_context,
|
audin->dsp_context->decode_ima_adpcm(audin->dsp_context,
|
||||||
Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
|
Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
|
||||||
size = audin->dsp_context->adpcm_size;
|
size = audin->dsp_context->adpcm_size;
|
||||||
src = audin->dsp_context->adpcm_buffer;
|
src = audin->dsp_context->adpcm_buffer;
|
||||||
sbytes_per_sample = 2;
|
sbytes_per_sample = 2;
|
||||||
@ -359,25 +378,26 @@ 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;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
audin->dsp_context->resample(audin->dsp_context, src, sbytes_per_sample,
|
audin->dsp_context->resample(audin->dsp_context, src, sbytes_per_sample,
|
||||||
format->nChannels, format->nSamplesPerSec, size / sbytes_per_frame,
|
format->nChannels, format->nSamplesPerSec, size / sbytes_per_frame,
|
||||||
audin->context.dst_format.nChannels, audin->context.dst_format.nSamplesPerSec);
|
audin->context.dst_format.nChannels, audin->context.dst_format.nSamplesPerSec);
|
||||||
frames = audin->dsp_context->resampled_frames;
|
frames = audin->dsp_context->resampled_frames;
|
||||||
src = audin->dsp_context->resampled_buffer;
|
src = audin->dsp_context->resampled_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFCALLRET(audin->context.ReceiveSamples, success, &audin->context, src, frames);
|
IFCALLRET(audin->context.ReceiveSamples, success, &audin->context, src, frames);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
WLog_ERR(TAG, "context.ReceiveSamples failed with error %lu", success);
|
WLog_ERR(TAG, "context.ReceiveSamples failed with error %lu", success);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* audin_server_thread_func(void* arg)
|
static void* audin_server_thread_func(void* arg)
|
||||||
@ -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,17 +441,19 @@ 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)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||||
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,14 +487,15 @@ 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)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream_SetPosition(s, 0);
|
Stream_SetPosition(s, 0);
|
||||||
@ -484,12 +506,15 @@ 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)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||||
error = ERROR_INTERNAL_ERROR;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
@ -504,14 +529,16 @@ static void* audin_server_thread_func(void* arg)
|
|||||||
case MSG_SNDIN_VERSION:
|
case MSG_SNDIN_VERSION:
|
||||||
if ((error = audin_server_recv_version(audin, s, BytesReturned)))
|
if ((error = audin_server_recv_version(audin, s, BytesReturned)))
|
||||||
{
|
{
|
||||||
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,18 +608,17 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
audin->audin_channel = WTSVirtualChannelOpenEx(audin->SessionId,
|
audin->audin_channel = WTSVirtualChannelOpenEx(audin->SessionId,
|
||||||
"AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
|
"AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
|
||||||
|
|
||||||
if (!audin->audin_channel)
|
if (!audin->audin_channel)
|
||||||
{
|
{
|
||||||
@ -601,7 +633,7 @@ static BOOL audin_server_open(audin_server_context* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(audin->thread = CreateThread(NULL, 0,
|
if (!(audin->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL)))
|
(LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
CloseHandle(audin->stopEvent);
|
CloseHandle(audin->stopEvent);
|
||||||
@ -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,11 +655,12 @@ 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());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(audin->thread);
|
CloseHandle(audin->thread);
|
||||||
CloseHandle(audin->stopEvent);
|
CloseHandle(audin->stopEvent);
|
||||||
@ -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)
|
||||||
|
@ -64,7 +64,7 @@ CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags,
|
static wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags,
|
||||||
UINT32 dataLen)
|
UINT32 dataLen)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
s = Stream_New(NULL, dataLen + 8);
|
s = Stream_New(NULL, dataLen + 8);
|
||||||
@ -109,12 +109,12 @@ static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = cliprdr->channelEntryPoints.pVirtualChannelWrite(cliprdr->OpenHandle,
|
status = cliprdr->channelEntryPoints.pVirtualChannelWrite(cliprdr->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ static void cliprdr_print_general_capability_flags(UINT32 flags)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr,
|
static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
UINT32 version;
|
UINT32 version;
|
||||||
UINT32 generalFlags;
|
UINT32 generalFlags;
|
||||||
@ -168,15 +168,15 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr,
|
|||||||
|
|
||||||
if (cliprdr->useLongFormatNames)
|
if (cliprdr->useLongFormatNames)
|
||||||
cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE :
|
cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE :
|
||||||
FALSE;
|
FALSE;
|
||||||
|
|
||||||
if (cliprdr->streamFileClipEnabled)
|
if (cliprdr->streamFileClipEnabled)
|
||||||
cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ?
|
cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ?
|
||||||
TRUE : FALSE;
|
TRUE : FALSE;
|
||||||
|
|
||||||
if (cliprdr->fileClipNoFilePaths)
|
if (cliprdr->fileClipNoFilePaths)
|
||||||
cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ?
|
cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ?
|
||||||
TRUE : FALSE;
|
TRUE : FALSE;
|
||||||
|
|
||||||
if (cliprdr->canLockClipData)
|
if (cliprdr->canLockClipData)
|
||||||
cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE;
|
cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE;
|
||||||
@ -191,7 +191,7 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr,
|
|||||||
|
|
||||||
capabilities.cCapabilitiesSets = 1;
|
capabilities.cCapabilitiesSets = 1;
|
||||||
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &
|
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &
|
||||||
(generalCapabilitySet);
|
(generalCapabilitySet);
|
||||||
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
|
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
|
||||||
generalCapabilitySet.capabilitySetLength = 12;
|
generalCapabilitySet.capabilitySetLength = 12;
|
||||||
generalCapabilitySet.version = version;
|
generalCapabilitySet.version = version;
|
||||||
@ -210,7 +210,7 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
|
static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
|
||||||
UINT16 length, UINT16 flags)
|
UINT16 length, UINT16 flags)
|
||||||
{
|
{
|
||||||
UINT16 index;
|
UINT16 index;
|
||||||
UINT16 lengthCapability;
|
UINT16 lengthCapability;
|
||||||
@ -232,7 +232,7 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
|
|||||||
if ((error = cliprdr_process_general_capability(cliprdr, s)))
|
if ((error = cliprdr_process_general_capability(cliprdr, s)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "cliprdr_process_general_capability failed with error %lu!",
|
WLog_ERR(TAG, "cliprdr_process_general_capability failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s,
|
static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s,
|
||||||
UINT16 length, UINT16 flags)
|
UINT16 length, UINT16 flags)
|
||||||
{
|
{
|
||||||
CLIPRDR_MONITOR_READY monitorReady;
|
CLIPRDR_MONITOR_READY monitorReady;
|
||||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
@ -298,7 +298,7 @@ static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr,
|
static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr,
|
||||||
wStream* s, UINT32 length, UINT16 flags)
|
wStream* s, UINT32 length, UINT16 flags)
|
||||||
{
|
{
|
||||||
CLIPRDR_FILE_CONTENTS_REQUEST request;
|
CLIPRDR_FILE_CONTENTS_REQUEST request;
|
||||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
@ -346,7 +346,7 @@ static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr,
|
static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr,
|
||||||
wStream* s, UINT32 length, UINT16 flags)
|
wStream* s, UINT32 length, UINT16 flags)
|
||||||
{
|
{
|
||||||
CLIPRDR_FILE_CONTENTS_RESPONSE response;
|
CLIPRDR_FILE_CONTENTS_RESPONSE response;
|
||||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
@ -385,7 +385,7 @@ static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
|
static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
|
||||||
UINT32 length, UINT16 flags)
|
UINT32 length, UINT16 flags)
|
||||||
{
|
{
|
||||||
CLIPRDR_LOCK_CLIPBOARD_DATA lockClipboardData;
|
CLIPRDR_LOCK_CLIPBOARD_DATA lockClipboardData;
|
||||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
@ -422,7 +422,7 @@ static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
|
static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
|
||||||
UINT32 length, UINT16 flags)
|
UINT32 length, UINT16 flags)
|
||||||
{
|
{
|
||||||
CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData;
|
CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData;
|
||||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
@ -445,9 +445,9 @@ static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
|
|||||||
unlockClipboardData.msgFlags = flags;
|
unlockClipboardData.msgFlags = flags;
|
||||||
unlockClipboardData.dataLen = length;
|
unlockClipboardData.dataLen = length;
|
||||||
Stream_Read_UINT32(s,
|
Stream_Read_UINT32(s,
|
||||||
unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */
|
unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */
|
||||||
IFCALLRET(context->ServerUnlockClipboardData, error, context,
|
IFCALLRET(context->ServerUnlockClipboardData, error, context,
|
||||||
&unlockClipboardData);
|
&unlockClipboardData);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
WLog_ERR(TAG, "ServerUnlockClipboardData failed with error %lu!", error);
|
WLog_ERR(TAG, "ServerUnlockClipboardData failed with error %lu!", error);
|
||||||
@ -471,7 +471,7 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
|
|||||||
Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */
|
Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */
|
||||||
#ifdef WITH_DEBUG_CLIPRDR
|
#ifdef WITH_DEBUG_CLIPRDR
|
||||||
WLog_DBG(TAG, "msgType: %s (%d), msgFlags: %d dataLen: %d",
|
WLog_DBG(TAG, "msgType: %s (%d), msgFlags: %d dataLen: %d",
|
||||||
CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
|
CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
|
||||||
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8);
|
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -497,41 +497,41 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
|
|||||||
|
|
||||||
case CB_FORMAT_LIST_RESPONSE:
|
case CB_FORMAT_LIST_RESPONSE:
|
||||||
if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen,
|
if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen,
|
||||||
msgFlags)))
|
msgFlags)))
|
||||||
WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %lu!",
|
WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CB_FORMAT_DATA_REQUEST:
|
case CB_FORMAT_DATA_REQUEST:
|
||||||
if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen,
|
if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen,
|
||||||
msgFlags)))
|
msgFlags)))
|
||||||
WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %lu!",
|
WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CB_FORMAT_DATA_RESPONSE:
|
case CB_FORMAT_DATA_RESPONSE:
|
||||||
if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen,
|
if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen,
|
||||||
msgFlags)))
|
msgFlags)))
|
||||||
WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %lu!",
|
WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CB_FILECONTENTS_REQUEST:
|
case CB_FILECONTENTS_REQUEST:
|
||||||
if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen,
|
if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen,
|
||||||
msgFlags)))
|
msgFlags)))
|
||||||
WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %lu!",
|
WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CB_FILECONTENTS_RESPONSE:
|
case CB_FILECONTENTS_RESPONSE:
|
||||||
if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen,
|
if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen,
|
||||||
msgFlags)))
|
msgFlags)))
|
||||||
WLog_ERR(TAG, "cliprdr_process_filecontents_response failed with error %lu!",
|
WLog_ERR(TAG, "cliprdr_process_filecontents_response failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -567,7 +567,7 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
|
static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
|
||||||
CLIPRDR_CAPABILITIES* capabilities)
|
CLIPRDR_CAPABILITIES* capabilities)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet;
|
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet;
|
||||||
@ -583,11 +583,11 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
|
|||||||
Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */
|
Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */
|
||||||
Stream_Write_UINT16(s, 0); /* pad1 */
|
Stream_Write_UINT16(s, 0); /* pad1 */
|
||||||
generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*)
|
generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*)
|
||||||
capabilities->capabilitySets;
|
capabilities->capabilitySets;
|
||||||
Stream_Write_UINT16(s,
|
Stream_Write_UINT16(s,
|
||||||
generalCapabilitySet->capabilitySetType); /* capabilitySetType */
|
generalCapabilitySet->capabilitySetType); /* capabilitySetType */
|
||||||
Stream_Write_UINT16(s,
|
Stream_Write_UINT16(s,
|
||||||
generalCapabilitySet->capabilitySetLength); /* lengthCapability */
|
generalCapabilitySet->capabilitySetLength); /* lengthCapability */
|
||||||
Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */
|
Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */
|
||||||
Stream_Write_UINT32(s, generalCapabilitySet->generalFlags); /* generalFlags */
|
Stream_Write_UINT32(s, generalCapabilitySet->generalFlags); /* generalFlags */
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientCapabilities");
|
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientCapabilities");
|
||||||
@ -600,7 +600,7 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_temp_directory(CliprdrClientContext* context,
|
static UINT cliprdr_temp_directory(CliprdrClientContext* context,
|
||||||
CLIPRDR_TEMP_DIRECTORY* tempDirectory)
|
CLIPRDR_TEMP_DIRECTORY* tempDirectory)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
wStream* s;
|
wStream* s;
|
||||||
@ -615,7 +615,7 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir,
|
length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
@ -627,7 +627,7 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
|
|||||||
Stream_Zero(s, (520 - length) * 2);
|
Stream_Zero(s, (520 - length) * 2);
|
||||||
free(wszTempDir);
|
free(wszTempDir);
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s",
|
WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s",
|
||||||
tempDirectory->szTempDir);
|
tempDirectory->szTempDir);
|
||||||
return cliprdr_packet_send(cliprdr, s);
|
return cliprdr_packet_send(cliprdr, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,7 +637,7 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
||||||
CLIPRDR_FORMAT_LIST* formatList)
|
CLIPRDR_FORMAT_LIST* formatList)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
UINT32 index;
|
UINT32 index;
|
||||||
@ -688,7 +688,7 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
|||||||
|
|
||||||
if (szFormatName)
|
if (szFormatName)
|
||||||
formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName,
|
formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (formatNameSize > 15)
|
if (formatNameSize > 15)
|
||||||
formatNameSize = 15;
|
formatNameSize = 15;
|
||||||
@ -711,7 +711,7 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
|||||||
|
|
||||||
if (format->formatName)
|
if (format->formatName)
|
||||||
formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL,
|
formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL,
|
||||||
0) * 2;
|
0) * 2;
|
||||||
|
|
||||||
length += formatNameSize;
|
length += formatNameSize;
|
||||||
}
|
}
|
||||||
@ -734,7 +734,7 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
|||||||
lpWideCharStr = (LPWSTR) Stream_Pointer(s);
|
lpWideCharStr = (LPWSTR) Stream_Pointer(s);
|
||||||
cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2;
|
cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2;
|
||||||
formatNameSize = MultiByteToWideChar(CP_UTF8, 0,
|
formatNameSize = MultiByteToWideChar(CP_UTF8, 0,
|
||||||
format->formatName, -1, lpWideCharStr, cchWideChar) * 2;
|
format->formatName, -1, lpWideCharStr, cchWideChar) * 2;
|
||||||
Stream_Seek(s, formatNameSize);
|
Stream_Seek(s, formatNameSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -745,7 +745,7 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatList: numFormats: %d",
|
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatList: numFormats: %d",
|
||||||
formatList->numFormats);
|
formatList->numFormats);
|
||||||
return cliprdr_packet_send(cliprdr, s);
|
return cliprdr_packet_send(cliprdr, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,14 +755,14 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_format_list_response(CliprdrClientContext* context,
|
static UINT cliprdr_client_format_list_response(CliprdrClientContext* context,
|
||||||
CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||||
formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE;
|
formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE;
|
||||||
formatListResponse->dataLen = 0;
|
formatListResponse->dataLen = 0;
|
||||||
s = cliprdr_packet_new(formatListResponse->msgType,
|
s = cliprdr_packet_new(formatListResponse->msgType,
|
||||||
formatListResponse->msgFlags, formatListResponse->dataLen);
|
formatListResponse->msgFlags, formatListResponse->dataLen);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -780,7 +780,7 @@ static UINT cliprdr_client_format_list_response(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
|
static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
|
||||||
CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||||
@ -793,10 +793,10 @@ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write_UINT32(s,
|
Stream_Write_UINT32(s,
|
||||||
lockClipboardData->clipDataId); /* clipDataId (4 bytes) */
|
lockClipboardData->clipDataId); /* clipDataId (4 bytes) */
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG,
|
WLog_Print(cliprdr->log, WLOG_DEBUG,
|
||||||
"ClientLockClipboardData: clipDataId: 0x%04X",
|
"ClientLockClipboardData: clipDataId: 0x%04X",
|
||||||
lockClipboardData->clipDataId);
|
lockClipboardData->clipDataId);
|
||||||
return cliprdr_packet_send(cliprdr, s);;
|
return cliprdr_packet_send(cliprdr, s);;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -806,7 +806,7 @@ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
|
static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
|
||||||
CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||||
@ -819,10 +819,10 @@ static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write_UINT32(s,
|
Stream_Write_UINT32(s,
|
||||||
unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */
|
unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG,
|
WLog_Print(cliprdr->log, WLOG_DEBUG,
|
||||||
"ClientUnlockClipboardData: clipDataId: 0x%04X",
|
"ClientUnlockClipboardData: clipDataId: 0x%04X",
|
||||||
unlockClipboardData->clipDataId);
|
unlockClipboardData->clipDataId);
|
||||||
return cliprdr_packet_send(cliprdr, s);
|
return cliprdr_packet_send(cliprdr, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -832,7 +832,7 @@ static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
|
static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
|
||||||
CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||||
@ -840,7 +840,7 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
|
|||||||
formatDataRequest->msgFlags = 0;
|
formatDataRequest->msgFlags = 0;
|
||||||
formatDataRequest->dataLen = 4;
|
formatDataRequest->dataLen = 4;
|
||||||
s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags,
|
s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags,
|
||||||
formatDataRequest->dataLen);
|
formatDataRequest->dataLen);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -849,7 +849,7 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write_UINT32(s,
|
Stream_Write_UINT32(s,
|
||||||
formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
|
formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataRequest");
|
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataRequest");
|
||||||
return cliprdr_packet_send(cliprdr, s);
|
return cliprdr_packet_send(cliprdr, s);
|
||||||
}
|
}
|
||||||
@ -860,13 +860,13 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
|
static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
|
||||||
CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||||
formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE;
|
formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE;
|
||||||
s = cliprdr_packet_new(formatDataResponse->msgType,
|
s = cliprdr_packet_new(formatDataResponse->msgType,
|
||||||
formatDataResponse->msgFlags, formatDataResponse->dataLen);
|
formatDataResponse->msgFlags, formatDataResponse->dataLen);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -875,7 +875,7 @@ static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write(s, formatDataResponse->requestedFormatData,
|
Stream_Write(s, formatDataResponse->requestedFormatData,
|
||||||
formatDataResponse->dataLen);
|
formatDataResponse->dataLen);
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataResponse");
|
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataResponse");
|
||||||
return cliprdr_packet_send(cliprdr, s);
|
return cliprdr_packet_send(cliprdr, s);
|
||||||
}
|
}
|
||||||
@ -886,7 +886,7 @@ static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
|
static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
|
||||||
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||||
@ -900,19 +900,19 @@ static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
|
|||||||
|
|
||||||
Stream_Write_UINT32(s, fileContentsRequest->streamId); /* streamId (4 bytes) */
|
Stream_Write_UINT32(s, fileContentsRequest->streamId); /* streamId (4 bytes) */
|
||||||
Stream_Write_UINT32(s,
|
Stream_Write_UINT32(s,
|
||||||
fileContentsRequest->listIndex); /* listIndex (4 bytes) */
|
fileContentsRequest->listIndex); /* listIndex (4 bytes) */
|
||||||
Stream_Write_UINT32(s, fileContentsRequest->dwFlags); /* dwFlags (4 bytes) */
|
Stream_Write_UINT32(s, fileContentsRequest->dwFlags); /* dwFlags (4 bytes) */
|
||||||
Stream_Write_UINT32(s,
|
Stream_Write_UINT32(s,
|
||||||
fileContentsRequest->nPositionLow); /* nPositionLow (4 bytes) */
|
fileContentsRequest->nPositionLow); /* nPositionLow (4 bytes) */
|
||||||
Stream_Write_UINT32(s,
|
Stream_Write_UINT32(s,
|
||||||
fileContentsRequest->nPositionHigh); /* nPositionHigh (4 bytes) */
|
fileContentsRequest->nPositionHigh); /* nPositionHigh (4 bytes) */
|
||||||
Stream_Write_UINT32(s,
|
Stream_Write_UINT32(s,
|
||||||
fileContentsRequest->cbRequested); /* cbRequested (4 bytes) */
|
fileContentsRequest->cbRequested); /* cbRequested (4 bytes) */
|
||||||
Stream_Write_UINT32(s,
|
Stream_Write_UINT32(s,
|
||||||
fileContentsRequest->clipDataId); /* clipDataId (4 bytes) */
|
fileContentsRequest->clipDataId); /* clipDataId (4 bytes) */
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG,
|
WLog_Print(cliprdr->log, WLOG_DEBUG,
|
||||||
"ClientFileContentsRequest: streamId: 0x%04X",
|
"ClientFileContentsRequest: streamId: 0x%04X",
|
||||||
fileContentsRequest->streamId);
|
fileContentsRequest->streamId);
|
||||||
return cliprdr_packet_send(cliprdr, s);
|
return cliprdr_packet_send(cliprdr, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,7 +922,7 @@ static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context,
|
static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context,
|
||||||
CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||||
@ -931,7 +931,7 @@ static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context,
|
|||||||
fileContentsResponse->cbRequested = sizeof(UINT64);
|
fileContentsResponse->cbRequested = sizeof(UINT64);
|
||||||
|
|
||||||
s = cliprdr_packet_new(CB_FILECONTENTS_RESPONSE, fileContentsResponse->msgFlags,
|
s = cliprdr_packet_new(CB_FILECONTENTS_RESPONSE, fileContentsResponse->msgFlags,
|
||||||
4 + fileContentsResponse->cbRequested);
|
4 + fileContentsResponse->cbRequested);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -946,10 +946,10 @@ static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context,
|
|||||||
* FILECONTENTS_RANGE: file data from requested range
|
* FILECONTENTS_RANGE: file data from requested range
|
||||||
*/
|
*/
|
||||||
Stream_Write(s, fileContentsResponse->requestedData,
|
Stream_Write(s, fileContentsResponse->requestedData,
|
||||||
fileContentsResponse->cbRequested);
|
fileContentsResponse->cbRequested);
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG,
|
WLog_Print(cliprdr->log, WLOG_DEBUG,
|
||||||
"ClientFileContentsResponse: streamId: 0x%04X",
|
"ClientFileContentsResponse: streamId: 0x%04X",
|
||||||
fileContentsResponse->streamId);
|
fileContentsResponse->streamId);
|
||||||
return cliprdr_packet_send(cliprdr, s);
|
return cliprdr_packet_send(cliprdr, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -959,7 +959,7 @@ static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr,
|
static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr,
|
||||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
wStream* data_in;
|
wStream* data_in;
|
||||||
|
|
||||||
@ -1014,8 +1014,8 @@ static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle,
|
static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle,
|
||||||
UINT event,
|
UINT event,
|
||||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
cliprdrPlugin* cliprdr = s_TLSPluginContext;
|
cliprdrPlugin* cliprdr = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1030,7 +1030,7 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||||
error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength,
|
error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength,
|
||||||
totalLength, dataFlags);
|
totalLength, dataFlags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_WRITE_COMPLETE:
|
case CHANNEL_EVENT_WRITE_COMPLETE:
|
||||||
@ -1043,7 +1043,7 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle,
|
|||||||
|
|
||||||
if (error && cliprdr->context->rdpcontext)
|
if (error && cliprdr->context->rdpcontext)
|
||||||
setChannelError(cliprdr->context->rdpcontext, error,
|
setChannelError(cliprdr->context->rdpcontext, error,
|
||||||
"cliprdr_virtual_channel_open_event reported an error");
|
"cliprdr_virtual_channel_open_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* cliprdr_virtual_channel_client_thread(void* arg)
|
static void* cliprdr_virtual_channel_client_thread(void* arg)
|
||||||
@ -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)
|
||||||
@ -1088,7 +1087,7 @@ static void* cliprdr_virtual_channel_client_thread(void* arg)
|
|||||||
|
|
||||||
if (error && cliprdr->context->rdpcontext)
|
if (error && cliprdr->context->rdpcontext)
|
||||||
setChannelError(cliprdr->context->rdpcontext, error,
|
setChannelError(cliprdr->context->rdpcontext, error,
|
||||||
"cliprdr_virtual_channel_client_thread reported an error");
|
"cliprdr_virtual_channel_client_thread reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD)error);
|
ExitThread((DWORD)error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1100,17 +1099,17 @@ static void* cliprdr_virtual_channel_client_thread(void* arg)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr,
|
static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr,
|
||||||
LPVOID pData, UINT32 dataLength)
|
LPVOID pData, UINT32 dataLength)
|
||||||
{
|
{
|
||||||
UINT32 status;
|
UINT32 status;
|
||||||
status = cliprdr->channelEntryPoints.pVirtualChannelOpen(cliprdr->InitHandle,
|
status = cliprdr->channelEntryPoints.pVirtualChannelOpen(cliprdr->InitHandle,
|
||||||
&cliprdr->OpenHandle, cliprdr->channelDef.name,
|
&cliprdr->OpenHandle, cliprdr->channelDef.name,
|
||||||
cliprdr_virtual_channel_open_event);
|
cliprdr_virtual_channel_open_event);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1123,8 +1122,8 @@ static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(cliprdr->thread = CreateThread(NULL, 0,
|
if (!(cliprdr->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) cliprdr_virtual_channel_client_thread, (void*) cliprdr,
|
(LPTHREAD_START_ROUTINE) cliprdr_virtual_channel_client_thread, (void*) cliprdr,
|
||||||
0, NULL)))
|
0, NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
MessageQueue_Free(cliprdr->queue);
|
MessageQueue_Free(cliprdr->queue);
|
||||||
@ -1159,7 +1158,7 @@ static UINT cliprdr_virtual_channel_event_disconnected(cliprdrPlugin* cliprdr)
|
|||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1186,8 +1185,8 @@ static UINT cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle,
|
static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle,
|
||||||
UINT event, LPVOID pData,
|
UINT event, LPVOID pData,
|
||||||
UINT dataLength)
|
UINT dataLength)
|
||||||
{
|
{
|
||||||
cliprdrPlugin* cliprdr = s_TLSPluginContext;
|
cliprdrPlugin* cliprdr = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1202,30 +1201,30 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_CONNECTED:
|
case CHANNEL_EVENT_CONNECTED:
|
||||||
if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData,
|
if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData,
|
||||||
dataLength)))
|
dataLength)))
|
||||||
WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %lu!",
|
WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_DISCONNECTED:
|
case CHANNEL_EVENT_DISCONNECTED:
|
||||||
if ((error = cliprdr_virtual_channel_event_disconnected(cliprdr)))
|
if ((error = cliprdr_virtual_channel_event_disconnected(cliprdr)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"cliprdr_virtual_channel_event_disconnected failed with error %lu!", error);
|
"cliprdr_virtual_channel_event_disconnected failed with error %lu!", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_TERMINATED:
|
case CHANNEL_EVENT_TERMINATED:
|
||||||
if ((error = cliprdr_virtual_channel_event_terminated(cliprdr)))
|
if ((error = cliprdr_virtual_channel_event_terminated(cliprdr)))
|
||||||
WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %lu!",
|
WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error && cliprdr->context->rdpcontext)
|
if (error && cliprdr->context->rdpcontext)
|
||||||
setChannelError(cliprdr->context->rdpcontext, error,
|
setChannelError(cliprdr->context->rdpcontext, error,
|
||||||
"cliprdr_virtual_channel_init_event reported an error");
|
"cliprdr_virtual_channel_init_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cliprdr is always built-in */
|
/* cliprdr is always built-in */
|
||||||
@ -1289,15 +1288,16 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
cliprdr->canLockClipData = FALSE;
|
cliprdr->canLockClipData = FALSE;
|
||||||
WLog_Print(cliprdr->log, WLOG_DEBUG, "VirtualChannelEntry");
|
WLog_Print(cliprdr->log, WLOG_DEBUG, "VirtualChannelEntry");
|
||||||
CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints,
|
CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints,
|
||||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||||
rc = cliprdr->channelEntryPoints.pVirtualChannelInit(&cliprdr->InitHandle,
|
rc = cliprdr->channelEntryPoints.pVirtualChannelInit(&cliprdr->InitHandle,
|
||||||
&cliprdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
&cliprdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||||
cliprdr_virtual_channel_init_event);
|
cliprdr_virtual_channel_init_event);
|
||||||
|
|
||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
@ -1307,9 +1307,9 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cliprdr->channelEntryPoints.pInterface = *
|
cliprdr->channelEntryPoints.pInterface = *
|
||||||
(cliprdr->channelEntryPoints.ppInterface);
|
(cliprdr->channelEntryPoints.ppInterface);
|
||||||
cliprdr->channelEntryPoints.ppInterface = &
|
cliprdr->channelEntryPoints.ppInterface = &
|
||||||
(cliprdr->channelEntryPoints.pInterface);
|
(cliprdr->channelEntryPoints.pInterface);
|
||||||
s_TLSPluginContext = cliprdr;
|
s_TLSPluginContext = cliprdr;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@ static WINPR_TLS drdynvcPlugin* s_TLSPluginContext = NULL;
|
|||||||
|
|
||||||
static void dvcman_channel_free(void* channel);
|
static void dvcman_channel_free(void* channel);
|
||||||
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
|
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
|
||||||
const BYTE* data, UINT32 dataSize);
|
const BYTE* data, UINT32 dataSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function description
|
* Function description
|
||||||
@ -42,7 +42,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_get_configuration(IWTSListener* pListener,
|
static UINT dvcman_get_configuration(IWTSListener* pListener,
|
||||||
void** ppPropertyBag)
|
void** ppPropertyBag)
|
||||||
{
|
{
|
||||||
*ppPropertyBag = NULL;
|
*ppPropertyBag = NULL;
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
@ -54,8 +54,8 @@ static UINT dvcman_get_configuration(IWTSListener* pListener,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
|
static UINT dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
|
||||||
const char* pszChannelName, ULONG ulFlags,
|
const char* pszChannelName, ULONG ulFlags,
|
||||||
IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
|
IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
|
||||||
{
|
{
|
||||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||||
DVCMAN_LISTENER* listener;
|
DVCMAN_LISTENER* listener;
|
||||||
@ -105,7 +105,7 @@ static UINT dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints,
|
static UINT dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints,
|
||||||
const char* name, IWTSPlugin* pPlugin)
|
const char* name, IWTSPlugin* pPlugin)
|
||||||
{
|
{
|
||||||
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
|
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
|
||||||
|
|
||||||
@ -119,13 +119,13 @@ static UINT dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "register_plugin: Maximum DVC plugin number %d reached.",
|
WLog_ERR(TAG, "register_plugin: Maximum DVC plugin number %d reached.",
|
||||||
MAX_PLUGINS);
|
MAX_PLUGINS);
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints,
|
static IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints,
|
||||||
const char* name)
|
const char* name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
|
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
|
||||||
@ -158,8 +158,8 @@ static UINT32 dvcman_get_channel_id(IWTSVirtualChannel* channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager*
|
static IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager*
|
||||||
pChannelMgr,
|
pChannelMgr,
|
||||||
UINT32 ChannelId)
|
UINT32 ChannelId)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
@ -185,8 +185,8 @@ static IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager*
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager*
|
static void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager*
|
||||||
pChannelMgr,
|
pChannelMgr,
|
||||||
const char* ChannelName)
|
const char* ChannelName)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
@ -253,15 +253,15 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr,
|
static UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr,
|
||||||
ADDIN_ARGV* args,
|
ADDIN_ARGV* args,
|
||||||
rdpSettings* settings)
|
rdpSettings* settings)
|
||||||
{
|
{
|
||||||
DVCMAN_ENTRY_POINTS entryPoints;
|
DVCMAN_ENTRY_POINTS entryPoints;
|
||||||
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
|
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
|
||||||
WLog_INFO(TAG, "Loading Dynamic Virtual Channel %s", args->argv[0]);
|
WLog_INFO(TAG, "Loading Dynamic Virtual Channel %s", args->argv[0]);
|
||||||
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(
|
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(
|
||||||
args->argv[0],
|
args->argv[0],
|
||||||
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
|
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
|
||||||
|
|
||||||
if (pDVCPluginEntry)
|
if (pDVCPluginEntry)
|
||||||
{
|
{
|
||||||
@ -279,15 +279,15 @@ static UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager*
|
static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager*
|
||||||
pChannelMgr,
|
pChannelMgr,
|
||||||
UINT32 ChannelId, const char* ChannelName)
|
UINT32 ChannelId, const char* ChannelName)
|
||||||
{
|
{
|
||||||
DVCMAN_CHANNEL* channel;
|
DVCMAN_CHANNEL* channel;
|
||||||
|
|
||||||
if (dvcman_find_channel_by_id(pChannelMgr, ChannelId))
|
if (dvcman_find_channel_by_id(pChannelMgr, ChannelId))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Protocol error: Duplicated ChannelId %d (%s)!", ChannelId,
|
WLog_ERR(TAG, "Protocol error: Duplicated ChannelId %d (%s)!", ChannelId,
|
||||||
ChannelName);
|
ChannelName);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,13 +413,13 @@ static UINT dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize,
|
static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize,
|
||||||
const BYTE* pBuffer, void* pReserved)
|
const BYTE* pBuffer, void* pReserved)
|
||||||
{
|
{
|
||||||
UINT status;
|
UINT status;
|
||||||
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
|
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
|
||||||
EnterCriticalSection(&(channel->lock));
|
EnterCriticalSection(&(channel->lock));
|
||||||
status = drdynvc_write_data(channel->dvcman->drdynvc,
|
status = drdynvc_write_data(channel->dvcman->drdynvc,
|
||||||
channel->channel_id, pBuffer, cbSize);
|
channel->channel_id, pBuffer, cbSize);
|
||||||
LeaveCriticalSection(&(channel->lock));
|
LeaveCriticalSection(&(channel->lock));
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -442,7 +442,7 @@ static UINT dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
|
static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
|
||||||
UINT32 ChannelId, const char* ChannelName)
|
UINT32 ChannelId, const char* ChannelName)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
BOOL bAccept;
|
BOOL bAccept;
|
||||||
@ -474,18 +474,18 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
pCallback = NULL;
|
pCallback = NULL;
|
||||||
|
|
||||||
if ((error = listener->listener_callback->OnNewChannelConnection(
|
if ((error = listener->listener_callback->OnNewChannelConnection(
|
||||||
listener->listener_callback,
|
listener->listener_callback,
|
||||||
(IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback)) == CHANNEL_RC_OK
|
(IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback)) == CHANNEL_RC_OK
|
||||||
&& bAccept)
|
&& bAccept)
|
||||||
{
|
{
|
||||||
WLog_DBG(TAG, "listener %s created new channel %d",
|
WLog_DBG(TAG, "listener %s created new channel %d",
|
||||||
listener->channel_name, channel->channel_id);
|
listener->channel_name, channel->channel_id);
|
||||||
channel->status = 0;
|
channel->status = 0;
|
||||||
channel->channel_callback = pCallback;
|
channel->channel_callback = pCallback;
|
||||||
channel->pInterface = listener->iface.pInterface;
|
channel->pInterface = listener->iface.pInterface;
|
||||||
context = dvcman->drdynvc->context;
|
context = dvcman->drdynvc->context;
|
||||||
IFCALLRET(context->OnChannelConnected, error, context, ChannelName,
|
IFCALLRET(context->OnChannelConnected, error, context, ChannelName,
|
||||||
listener->iface.pInterface);
|
listener->iface.pInterface);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
WLog_ERR(TAG, "context.ReceiveSamples failed with error %lu", error);
|
WLog_ERR(TAG, "context.ReceiveSamples failed with error %lu", error);
|
||||||
@ -517,7 +517,7 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr,
|
static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr,
|
||||||
UINT32 ChannelId)
|
UINT32 ChannelId)
|
||||||
{
|
{
|
||||||
DVCMAN_CHANNEL* channel;
|
DVCMAN_CHANNEL* channel;
|
||||||
IWTSVirtualChannelCallback* pCallback;
|
IWTSVirtualChannelCallback* pCallback;
|
||||||
@ -552,7 +552,7 @@ static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr,
|
static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr,
|
||||||
UINT32 ChannelId)
|
UINT32 ChannelId)
|
||||||
{
|
{
|
||||||
DVCMAN_CHANNEL* channel;
|
DVCMAN_CHANNEL* channel;
|
||||||
IWTSVirtualChannel* ichannel;
|
IWTSVirtualChannel* ichannel;
|
||||||
@ -575,7 +575,7 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
{
|
{
|
||||||
context = dvcman->drdynvc->context;
|
context = dvcman->drdynvc->context;
|
||||||
IFCALLRET(context->OnChannelDisconnected, error, context, channel->channel_name,
|
IFCALLRET(context->OnChannelDisconnected, error, context, channel->channel_name,
|
||||||
channel->pInterface);
|
channel->pInterface);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -603,8 +603,8 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager*
|
static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager*
|
||||||
pChannelMgr,
|
pChannelMgr,
|
||||||
UINT32 ChannelId, UINT32 length)
|
UINT32 ChannelId, UINT32 length)
|
||||||
{
|
{
|
||||||
DVCMAN_CHANNEL* channel;
|
DVCMAN_CHANNEL* channel;
|
||||||
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||||
@ -636,7 +636,7 @@ static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager*
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr,
|
static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr,
|
||||||
UINT32 ChannelId, wStream* data)
|
UINT32 ChannelId, wStream* data)
|
||||||
{
|
{
|
||||||
UINT status = CHANNEL_RC_OK;
|
UINT status = CHANNEL_RC_OK;
|
||||||
DVCMAN_CHANNEL* channel;
|
DVCMAN_CHANNEL* channel;
|
||||||
@ -655,7 +655,7 @@ static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
{
|
{
|
||||||
/* Fragmented data */
|
/* Fragmented data */
|
||||||
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(
|
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(
|
||||||
channel->dvc_data))
|
channel->dvc_data))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "data exceeding declared length!");
|
WLog_ERR(TAG, "data exceeding declared length!");
|
||||||
Stream_Release(channel->dvc_data);
|
Stream_Release(channel->dvc_data);
|
||||||
@ -671,7 +671,7 @@ static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
Stream_SealLength(channel->dvc_data);
|
Stream_SealLength(channel->dvc_data);
|
||||||
Stream_SetPosition(channel->dvc_data, 0);
|
Stream_SetPosition(channel->dvc_data, 0);
|
||||||
status = channel->channel_callback->OnDataReceived(channel->channel_callback,
|
status = channel->channel_callback->OnDataReceived(channel->channel_callback,
|
||||||
channel->dvc_data);
|
channel->dvc_data);
|
||||||
Stream_Release(channel->dvc_data);
|
Stream_Release(channel->dvc_data);
|
||||||
channel->dvc_data = NULL;
|
channel->dvc_data = NULL;
|
||||||
}
|
}
|
||||||
@ -679,7 +679,7 @@ static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = channel->channel_callback->OnDataReceived(channel->channel_callback,
|
status = channel->channel_callback->OnDataReceived(channel->channel_callback,
|
||||||
data);
|
data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -724,14 +724,14 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = drdynvc->channelEntryPoints.pVirtualChannelWrite(drdynvc->OpenHandle,
|
status = drdynvc->channelEntryPoints.pVirtualChannelWrite(drdynvc->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -743,7 +743,7 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
|
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
|
||||||
const BYTE* data, UINT32 dataSize)
|
const BYTE* data, UINT32 dataSize)
|
||||||
{
|
{
|
||||||
wStream* data_out;
|
wStream* data_out;
|
||||||
unsigned long pos;
|
unsigned long pos;
|
||||||
@ -824,7 +824,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
|
|||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -850,14 +850,14 @@ static UINT drdynvc_send_capability_response(drdynvcPlugin* drdynvc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write_UINT16(s,
|
Stream_Write_UINT16(s,
|
||||||
0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */
|
0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */
|
||||||
Stream_Write_UINT16(s, drdynvc->version);
|
Stream_Write_UINT16(s, drdynvc->version);
|
||||||
status = drdynvc_send(drdynvc, s);
|
status = drdynvc_send(drdynvc, s);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -869,7 +869,7 @@ static UINT drdynvc_send_capability_response(drdynvcPlugin* drdynvc)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
|
static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
|
||||||
int cbChId, wStream* s)
|
int cbChId, wStream* s)
|
||||||
{
|
{
|
||||||
UINT status;
|
UINT status;
|
||||||
WLog_DBG(TAG, "capability_request Sp=%d cbChId=%d", Sp, cbChId);
|
WLog_DBG(TAG, "capability_request Sp=%d cbChId=%d", Sp, cbChId);
|
||||||
@ -920,7 +920,7 @@ static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
||||||
int cbChId, wStream* s)
|
int cbChId, wStream* s)
|
||||||
{
|
{
|
||||||
unsigned long pos;
|
unsigned long pos;
|
||||||
UINT status;
|
UINT status;
|
||||||
@ -949,9 +949,9 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||||
pos = Stream_GetPosition(s);
|
pos = Stream_GetPosition(s);
|
||||||
WLog_DBG(TAG, "process_create_request: ChannelId=%d ChannelName=%s", ChannelId,
|
WLog_DBG(TAG, "process_create_request: ChannelId=%d ChannelName=%s", ChannelId,
|
||||||
Stream_Pointer(s));
|
Stream_Pointer(s));
|
||||||
channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId,
|
channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId,
|
||||||
(char*) Stream_Pointer(s));
|
(char*) Stream_Pointer(s));
|
||||||
data_out = Stream_New(NULL, pos + 4);
|
data_out = Stream_New(NULL, pos + 4);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
@ -973,7 +973,7 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
{
|
{
|
||||||
WLog_DBG(TAG, "no listener");
|
WLog_DBG(TAG, "no listener");
|
||||||
Stream_Write_UINT32(data_out,
|
Stream_Write_UINT32(data_out,
|
||||||
(UINT32) 0xC0000001); /* same code used by mstsc */
|
(UINT32) 0xC0000001); /* same code used by mstsc */
|
||||||
}
|
}
|
||||||
|
|
||||||
status = drdynvc_send(drdynvc, data_out);
|
status = drdynvc_send(drdynvc, data_out);
|
||||||
@ -981,7 +981,7 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1008,7 +1008,7 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp,
|
static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp,
|
||||||
int cbChId, wStream* s)
|
int cbChId, wStream* s)
|
||||||
{
|
{
|
||||||
UINT status;
|
UINT status;
|
||||||
UINT32 Length;
|
UINT32 Length;
|
||||||
@ -1016,9 +1016,9 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||||
Length = drdynvc_read_variable_uint(s, Sp);
|
Length = drdynvc_read_variable_uint(s, Sp);
|
||||||
WLog_DBG(TAG, "process_data_first: Sp=%d cbChId=%d, ChannelId=%d Length=%d", Sp,
|
WLog_DBG(TAG, "process_data_first: Sp=%d cbChId=%d, ChannelId=%d Length=%d", Sp,
|
||||||
cbChId, ChannelId, Length);
|
cbChId, ChannelId, Length);
|
||||||
status = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId,
|
status = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId,
|
||||||
Length);
|
Length);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
@ -1032,12 +1032,12 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId,
|
static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
UINT32 ChannelId;
|
UINT32 ChannelId;
|
||||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||||
WLog_DBG(TAG, "process_data: Sp=%d cbChId=%d, ChannelId=%d", Sp, cbChId,
|
WLog_DBG(TAG, "process_data: Sp=%d cbChId=%d, ChannelId=%d", Sp, cbChId,
|
||||||
ChannelId);
|
ChannelId);
|
||||||
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
|
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1047,7 +1047,7 @@ static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
|
static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
|
||||||
int cbChId, wStream* s)
|
int cbChId, wStream* s)
|
||||||
{
|
{
|
||||||
int value;
|
int value;
|
||||||
UINT error;
|
UINT error;
|
||||||
@ -1055,7 +1055,7 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
wStream* data_out;
|
wStream* data_out;
|
||||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||||
WLog_DBG(TAG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%d", Sp,
|
WLog_DBG(TAG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%d", Sp,
|
||||||
cbChId, ChannelId);
|
cbChId, ChannelId);
|
||||||
|
|
||||||
if ((error = dvcman_close_channel(drdynvc->channel_mgr, ChannelId)))
|
if ((error = dvcman_close_channel(drdynvc->channel_mgr, ChannelId)))
|
||||||
{
|
{
|
||||||
@ -1078,7 +1078,7 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(error), error);
|
WTSErrorToString(error), error);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -1099,7 +1099,7 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s)
|
|||||||
Sp = (value & 0x0c) >> 2;
|
Sp = (value & 0x0c) >> 2;
|
||||||
cbChId = (value & 0x03) >> 0;
|
cbChId = (value & 0x03) >> 0;
|
||||||
WLog_DBG(TAG, "order_recv: Cmd=0x%x, Sp=%d cbChId=%d, ChannelId=%d", Cmd, Sp,
|
WLog_DBG(TAG, "order_recv: Cmd=0x%x, Sp=%d cbChId=%d, ChannelId=%d", Cmd, Sp,
|
||||||
cbChId);
|
cbChId);
|
||||||
|
|
||||||
switch (Cmd)
|
switch (Cmd)
|
||||||
{
|
{
|
||||||
@ -1136,7 +1136,7 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
|
static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
|
||||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
wStream* data_in;
|
wStream* data_in;
|
||||||
|
|
||||||
@ -1192,8 +1192,8 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle,
|
static void VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle,
|
||||||
UINT event,
|
UINT event,
|
||||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
drdynvcPlugin* drdynvc = s_TLSPluginContext;
|
drdynvcPlugin* drdynvc = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1208,9 +1208,9 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||||
if ((error = drdynvc_virtual_channel_event_data_received(drdynvc, pData,
|
if ((error = drdynvc_virtual_channel_event_data_received(drdynvc, pData,
|
||||||
dataLength, totalLength, dataFlags)))
|
dataLength, totalLength, dataFlags)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"drdynvc_virtual_channel_event_data_received failed with error %lu", error);
|
"drdynvc_virtual_channel_event_data_received failed with error %lu", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1224,7 +1224,7 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle,
|
|||||||
|
|
||||||
if (error && drdynvc->rdpcontext)
|
if (error && drdynvc->rdpcontext)
|
||||||
setChannelError(drdynvc->rdpcontext, error,
|
setChannelError(drdynvc->rdpcontext, error,
|
||||||
"drdynvc_virtual_channel_open_event reported an error");
|
"drdynvc_virtual_channel_open_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* drdynvc_virtual_channel_client_thread(void* arg)
|
static void* drdynvc_virtual_channel_client_thread(void* arg)
|
||||||
@ -1271,7 +1271,7 @@ static void* drdynvc_virtual_channel_client_thread(void* arg)
|
|||||||
|
|
||||||
if (error && drdynvc->rdpcontext)
|
if (error && drdynvc->rdpcontext)
|
||||||
setChannelError(drdynvc->rdpcontext, error,
|
setChannelError(drdynvc->rdpcontext, error,
|
||||||
"drdynvc_virtual_channel_client_thread reported an error");
|
"drdynvc_virtual_channel_client_thread reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD) error);
|
ExitThread((DWORD) error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1283,7 +1283,7 @@ static void* drdynvc_virtual_channel_client_thread(void* arg)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc,
|
static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc,
|
||||||
LPVOID pData, UINT32 dataLength)
|
LPVOID pData, UINT32 dataLength)
|
||||||
{
|
{
|
||||||
UINT32 status;
|
UINT32 status;
|
||||||
UINT32 index;
|
UINT32 index;
|
||||||
@ -1291,13 +1291,13 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc,
|
|||||||
rdpSettings* settings;
|
rdpSettings* settings;
|
||||||
UINT error;
|
UINT error;
|
||||||
status = drdynvc->channelEntryPoints.pVirtualChannelOpen(drdynvc->InitHandle,
|
status = drdynvc->channelEntryPoints.pVirtualChannelOpen(drdynvc->InitHandle,
|
||||||
&drdynvc->OpenHandle, drdynvc->channelDef.name,
|
&drdynvc->OpenHandle, drdynvc->channelDef.name,
|
||||||
drdynvc_virtual_channel_open_event);
|
drdynvc_virtual_channel_open_event);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,8 +1339,8 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc,
|
|||||||
drdynvc->state = DRDYNVC_STATE_CAPABILITIES;
|
drdynvc->state = DRDYNVC_STATE_CAPABILITIES;
|
||||||
|
|
||||||
if (!(drdynvc->thread = CreateThread(NULL, 0,
|
if (!(drdynvc->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) drdynvc_virtual_channel_client_thread, (void*) drdynvc,
|
(LPTHREAD_START_ROUTINE) drdynvc_virtual_channel_client_thread, (void*) drdynvc,
|
||||||
0, NULL)))
|
0, NULL)))
|
||||||
{
|
{
|
||||||
error = ERROR_INTERNAL_ERROR;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
@ -1377,7 +1377,7 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
|
|||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
drdynvc->OpenHandle = 0;
|
drdynvc->OpenHandle = 0;
|
||||||
@ -1410,8 +1410,8 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle,
|
static VOID VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle,
|
||||||
UINT event, LPVOID pData,
|
UINT event, LPVOID pData,
|
||||||
UINT dataLength)
|
UINT dataLength)
|
||||||
{
|
{
|
||||||
drdynvcPlugin* drdynvc = s_TLSPluginContext;
|
drdynvcPlugin* drdynvc = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1426,30 +1426,30 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_CONNECTED:
|
case CHANNEL_EVENT_CONNECTED:
|
||||||
if ((error = drdynvc_virtual_channel_event_connected(drdynvc, pData,
|
if ((error = drdynvc_virtual_channel_event_connected(drdynvc, pData,
|
||||||
dataLength)))
|
dataLength)))
|
||||||
WLog_ERR(TAG, "drdynvc_virtual_channel_event_connected failed with error %lu",
|
WLog_ERR(TAG, "drdynvc_virtual_channel_event_connected failed with error %lu",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_DISCONNECTED:
|
case CHANNEL_EVENT_DISCONNECTED:
|
||||||
if ((error = drdynvc_virtual_channel_event_disconnected(drdynvc)))
|
if ((error = drdynvc_virtual_channel_event_disconnected(drdynvc)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"drdynvc_virtual_channel_event_disconnected failed with error %lu", error);
|
"drdynvc_virtual_channel_event_disconnected failed with error %lu", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_TERMINATED:
|
case CHANNEL_EVENT_TERMINATED:
|
||||||
if ((error = drdynvc_virtual_channel_event_terminated(drdynvc)))
|
if ((error = drdynvc_virtual_channel_event_terminated(drdynvc)))
|
||||||
WLog_ERR(TAG, "drdynvc_virtual_channel_event_terminated failed with error %lu",
|
WLog_ERR(TAG, "drdynvc_virtual_channel_event_terminated failed with error %lu",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error && drdynvc->rdpcontext)
|
if (error && drdynvc->rdpcontext)
|
||||||
setChannelError(drdynvc->rdpcontext, error,
|
setChannelError(drdynvc->rdpcontext, error,
|
||||||
"drdynvc_virtual_channel_init_event reported an error");
|
"drdynvc_virtual_channel_init_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1510,15 +1510,16 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
drdynvc->log = WLog_Get("com.freerdp.channels.drdynvc.client");
|
drdynvc->log = WLog_Get("com.freerdp.channels.drdynvc.client");
|
||||||
WLog_Print(drdynvc->log, WLOG_DEBUG, "VirtualChannelEntry");
|
WLog_Print(drdynvc->log, WLOG_DEBUG, "VirtualChannelEntry");
|
||||||
CopyMemory(&(drdynvc->channelEntryPoints), pEntryPoints,
|
CopyMemory(&(drdynvc->channelEntryPoints), pEntryPoints,
|
||||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||||
rc = drdynvc->channelEntryPoints.pVirtualChannelInit(&drdynvc->InitHandle,
|
rc = drdynvc->channelEntryPoints.pVirtualChannelInit(&drdynvc->InitHandle,
|
||||||
&drdynvc->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
&drdynvc->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||||
drdynvc_virtual_channel_init_event);
|
drdynvc_virtual_channel_init_event);
|
||||||
|
|
||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
@ -1528,9 +1529,9 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
}
|
}
|
||||||
|
|
||||||
drdynvc->channelEntryPoints.pInterface = *
|
drdynvc->channelEntryPoints.pInterface = *
|
||||||
(drdynvc->channelEntryPoints.ppInterface);
|
(drdynvc->channelEntryPoints.ppInterface);
|
||||||
drdynvc->channelEntryPoints.ppInterface = &
|
drdynvc->channelEntryPoints.ppInterface = &
|
||||||
(drdynvc->channelEntryPoints.pInterface);
|
(drdynvc->channelEntryPoints.pInterface);
|
||||||
s_TLSPluginContext = drdynvc;
|
s_TLSPluginContext = drdynvc;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -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!");
|
||||||
@ -97,7 +99,7 @@ static void* drdynvc_server_thread(void* arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||||
break;
|
break;
|
||||||
@ -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,8 +135,9 @@ 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)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
CloseHandle(context->priv->StopEvent);
|
CloseHandle(context->priv->StopEvent);
|
||||||
@ -151,34 +155,32 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context)
|
|||||||
*/
|
*/
|
||||||
static UINT drdynvc_server_stop(DrdynvcServerContext* context)
|
static UINT drdynvc_server_stop(DrdynvcServerContext* 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)
|
||||||
{
|
{
|
||||||
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(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!");
|
||||||
|
@ -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,11 +150,9 @@ 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);
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
@ -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,19 +455,22 @@ 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 |
|
||||||
FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
|
FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
|
||||||
#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,14 +547,12 @@ 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);
|
||||||
|
|
||||||
if (status < 1)
|
if (status < 1)
|
||||||
if (!(path = (char*) calloc(1, 1)))
|
if (!(path = (char*) calloc(1, 1)))
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,24 +748,22 @@ static UINT drive_irp_request(DEVICE* device, IRP* irp)
|
|||||||
static UINT drive_free(DEVICE* device)
|
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();
|
{
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
error = GetLastError();
|
||||||
return error;
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||||
}
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -67,34 +67,34 @@ static UINT echo_server_open_channel(echo_server* echo)
|
|||||||
PULONG pSessionId = NULL;
|
PULONG pSessionId = NULL;
|
||||||
|
|
||||||
if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION,
|
if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION,
|
||||||
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE)
|
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
|
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
|
||||||
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();
|
||||||
|
|
||||||
while (echo->echo_channel == NULL)
|
while (echo->echo_channel == NULL)
|
||||||
{
|
{
|
||||||
if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED)
|
if (WaitForSingleObject(hEvent, 1000) == 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo->echo_channel = WTSVirtualChannelOpenEx(echo->SessionId,
|
echo->echo_channel = WTSVirtualChannelOpenEx(echo->SessionId,
|
||||||
"ECHO", WTS_CHANNEL_OPTION_DYNAMIC);
|
"ECHO", WTS_CHANNEL_OPTION_DYNAMIC);
|
||||||
|
|
||||||
if (echo->echo_channel)
|
if (echo->echo_channel)
|
||||||
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!");
|
||||||
@ -198,23 +213,24 @@ static void* echo_server_thread_func(void* arg)
|
|||||||
|
|
||||||
while (ready)
|
while (ready)
|
||||||
{
|
{
|
||||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
if (status == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0)
|
if (status == WAIT_OBJECT_0)
|
||||||
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!");
|
||||||
@ -223,26 +239,31 @@ static void* echo_server_thread_func(void* arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s),
|
if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s),
|
||||||
(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
|
(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||||
error = ERROR_INTERNAL_ERROR;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +306,7 @@ static UINT echo_server_open(echo_server_context* context)
|
|||||||
*/
|
*/
|
||||||
static UINT echo_server_close(echo_server_context* context)
|
static UINT echo_server_close(echo_server_context* context)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
echo_server* echo = (echo_server*) context;
|
echo_server* echo = (echo_server*) context;
|
||||||
|
|
||||||
if (echo->thread)
|
if (echo->thread)
|
||||||
@ -291,31 +314,31 @@ static UINT echo_server_close(echo_server_context* context)
|
|||||||
SetEvent(echo->stopEvent);
|
SetEvent(echo->stopEvent);
|
||||||
|
|
||||||
if (WaitForSingleObject(echo->thread, INFINITE) == WAIT_FAILED)
|
if (WaitForSingleObject(echo->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(echo->thread);
|
CloseHandle(echo->thread);
|
||||||
CloseHandle(echo->stopEvent);
|
CloseHandle(echo->stopEvent);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -121,11 +121,11 @@ static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s)
|
|||||||
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
|
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
|
||||||
#endif
|
#endif
|
||||||
status = encomsp->channelEntryPoints.pVirtualChannelWrite(encomsp->OpenHandle,
|
status = encomsp->channelEntryPoints.pVirtualChannelWrite(encomsp->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
|
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s,
|
static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s,
|
||||||
ENCOMSP_ORDER_HEADER* header)
|
ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -190,7 +190,7 @@ static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp,
|
static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp,
|
||||||
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -252,7 +252,7 @@ static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp,
|
static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp,
|
||||||
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -306,7 +306,7 @@ static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s,
|
static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s,
|
||||||
ENCOMSP_ORDER_HEADER* header)
|
ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -369,7 +369,7 @@ static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s,
|
static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s,
|
||||||
ENCOMSP_ORDER_HEADER* header)
|
ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -423,7 +423,7 @@ static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s,
|
static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s,
|
||||||
ENCOMSP_ORDER_HEADER* header)
|
ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -477,7 +477,7 @@ static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp,
|
static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp,
|
||||||
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -540,7 +540,7 @@ static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp,
|
static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp,
|
||||||
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -641,7 +641,7 @@ static UINT encomsp_recv_change_participant_control_level_pdu(
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu",
|
WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -687,7 +687,7 @@ static UINT encomsp_send_change_participant_control_level_pdu(
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp,
|
static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp,
|
||||||
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -733,7 +733,7 @@ static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp,
|
static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp,
|
||||||
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||||
{
|
{
|
||||||
int beg, end;
|
int beg, end;
|
||||||
EncomspClientContext* context;
|
EncomspClientContext* context;
|
||||||
@ -808,7 +808,7 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
|
|||||||
if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header)))
|
if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!",
|
WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -818,7 +818,7 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
|
|||||||
if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header)))
|
if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!",
|
WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -855,7 +855,7 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
|
|||||||
if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header)))
|
if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "encomsp_recv_participant_removed_pdu failed with error %lu!",
|
WLog_ERR(TAG, "encomsp_recv_participant_removed_pdu failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,7 +865,7 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
|
|||||||
if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header)))
|
if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "encomsp_recv_participant_created_pdu failed with error %lu!",
|
WLog_ERR(TAG, "encomsp_recv_participant_created_pdu failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -873,11 +873,11 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
|
|||||||
|
|
||||||
case ODTYPE_PARTICIPANT_CTRL_CHANGED:
|
case ODTYPE_PARTICIPANT_CTRL_CHANGED:
|
||||||
if ((error = encomsp_recv_change_participant_control_level_pdu(encomsp, s,
|
if ((error = encomsp_recv_change_participant_control_level_pdu(encomsp, s,
|
||||||
&header)))
|
&header)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"encomsp_recv_change_participant_control_level_pdu failed with error %lu!",
|
"encomsp_recv_change_participant_control_level_pdu failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,7 +887,7 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
|
|||||||
if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header)))
|
if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "encomsp_recv_graphics_stream_paused_pdu failed with error %lu!",
|
WLog_ERR(TAG, "encomsp_recv_graphics_stream_paused_pdu failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,7 +897,7 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
|
|||||||
if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header)))
|
if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "encomsp_recv_graphics_stream_resumed_pdu failed with error %lu!",
|
WLog_ERR(TAG, "encomsp_recv_graphics_stream_resumed_pdu failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -929,14 +929,14 @@ static int encomsp_send(encomspPlugin* encomsp, wStream* s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
|
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -948,7 +948,7 @@ static int encomsp_send(encomspPlugin* encomsp, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
|
static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
|
||||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
wStream* data_in;
|
wStream* data_in;
|
||||||
|
|
||||||
@ -1002,8 +1002,8 @@ static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle,
|
static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle,
|
||||||
UINT event,
|
UINT event,
|
||||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
encomspPlugin* encomsp = s_TLSPluginContext;
|
encomspPlugin* encomsp = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1018,9 +1018,9 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||||
if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData,
|
if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData,
|
||||||
dataLength, totalLength, dataFlags)))
|
dataLength, totalLength, dataFlags)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"encomsp_virtual_channel_event_data_received failed with error %lu", error);
|
"encomsp_virtual_channel_event_data_received failed with error %lu", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1034,7 +1034,7 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle,
|
|||||||
|
|
||||||
if (error && encomsp->rdpcontext)
|
if (error && encomsp->rdpcontext)
|
||||||
setChannelError(encomsp->rdpcontext, error,
|
setChannelError(encomsp->rdpcontext, error,
|
||||||
"encomsp_virtual_channel_open_event reported an error");
|
"encomsp_virtual_channel_open_event reported an error");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
|
|
||||||
@ -1082,7 +1081,7 @@ static void* encomsp_virtual_channel_client_thread(void* arg)
|
|||||||
|
|
||||||
if (error && encomsp->rdpcontext)
|
if (error && encomsp->rdpcontext)
|
||||||
setChannelError(encomsp->rdpcontext, error,
|
setChannelError(encomsp->rdpcontext, error,
|
||||||
"encomsp_virtual_channel_client_thread reported an error");
|
"encomsp_virtual_channel_client_thread reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD)error);
|
ExitThread((DWORD)error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1094,17 +1093,17 @@ static void* encomsp_virtual_channel_client_thread(void* arg)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
|
static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
|
||||||
LPVOID pData, UINT32 dataLength)
|
LPVOID pData, UINT32 dataLength)
|
||||||
{
|
{
|
||||||
UINT32 status;
|
UINT32 status;
|
||||||
status = encomsp->channelEntryPoints.pVirtualChannelOpen(encomsp->InitHandle,
|
status = encomsp->channelEntryPoints.pVirtualChannelOpen(encomsp->InitHandle,
|
||||||
&encomsp->OpenHandle, encomsp->channelDef.name,
|
&encomsp->OpenHandle, encomsp->channelDef.name,
|
||||||
encomsp_virtual_channel_open_event);
|
encomsp_virtual_channel_open_event);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,8 +1116,8 @@ static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(encomsp->thread = CreateThread(NULL, 0,
|
if (!(encomsp->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp,
|
(LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp,
|
||||||
0, NULL)))
|
0, NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
MessageQueue_Free(encomsp->queue);
|
MessageQueue_Free(encomsp->queue);
|
||||||
@ -1154,7 +1153,7 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
|
|||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1183,8 +1182,8 @@ static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle,
|
static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle,
|
||||||
UINT event, LPVOID pData,
|
UINT event, LPVOID pData,
|
||||||
UINT dataLength)
|
UINT dataLength)
|
||||||
{
|
{
|
||||||
encomspPlugin* encomsp = s_TLSPluginContext;
|
encomspPlugin* encomsp = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1199,16 +1198,16 @@ static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_CONNECTED:
|
case CHANNEL_EVENT_CONNECTED:
|
||||||
if ((error = encomsp_virtual_channel_event_connected(encomsp, pData,
|
if ((error = encomsp_virtual_channel_event_connected(encomsp, pData,
|
||||||
dataLength)))
|
dataLength)))
|
||||||
WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu",
|
WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_DISCONNECTED:
|
case CHANNEL_EVENT_DISCONNECTED:
|
||||||
if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
|
if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"encomsp_virtual_channel_event_disconnected failed with error %lu", error);
|
"encomsp_virtual_channel_event_disconnected failed with error %lu", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1222,7 +1221,7 @@ static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
|
|
||||||
if (error && encomsp->rdpcontext)
|
if (error && encomsp->rdpcontext)
|
||||||
setChannelError(encomsp->rdpcontext, error,
|
setChannelError(encomsp->rdpcontext, error,
|
||||||
"encomsp_virtual_channel_init_event reported an error");
|
"encomsp_virtual_channel_init_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* encomsp is always built-in */
|
/* encomsp is always built-in */
|
||||||
@ -1282,25 +1281,26 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints,
|
CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints,
|
||||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||||
rc = encomsp->channelEntryPoints.pVirtualChannelInit(&encomsp->InitHandle,
|
rc = encomsp->channelEntryPoints.pVirtualChannelInit(&encomsp->InitHandle,
|
||||||
&encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
&encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||||
encomsp_virtual_channel_init_event);
|
encomsp_virtual_channel_init_event);
|
||||||
|
|
||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
encomsp->channelEntryPoints.pInterface = *
|
encomsp->channelEntryPoints.pInterface = *
|
||||||
(encomsp->channelEntryPoints.ppInterface);
|
(encomsp->channelEntryPoints.ppInterface);
|
||||||
encomsp->channelEntryPoints.ppInterface = &
|
encomsp->channelEntryPoints.ppInterface = &
|
||||||
(encomsp->channelEntryPoints.pInterface);
|
(encomsp->channelEntryPoints.pInterface);
|
||||||
s_TLSPluginContext = encomsp;
|
s_TLSPluginContext = encomsp;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
error_out:
|
error_out:
|
||||||
|
|
||||||
if (context)
|
if (context)
|
||||||
*(pEntryPointsEx->ppInterface) = NULL;
|
*(pEntryPointsEx->ppInterface) = NULL;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,16 +185,14 @@ static void* encomsp_server_thread(void* arg)
|
|||||||
ENCOMSP_ORDER_HEADER* header;
|
ENCOMSP_ORDER_HEADER* header;
|
||||||
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));
|
||||||
@ -214,23 +215,23 @@ static void* encomsp_server_thread(void* arg)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
if (status == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
if (status == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0)
|
if (status == WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
@ -238,16 +239,19 @@ 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))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||||
error = ERROR_INTERNAL_ERROR;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
@ -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;
|
||||||
@ -300,7 +309,7 @@ static UINT encomsp_server_start(EncomspServerContext* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(context->priv->Thread = CreateThread(NULL, 0,
|
if (!(context->priv->Thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) encomsp_server_thread, (void*) context, 0, NULL)))
|
(LPTHREAD_START_ROUTINE) encomsp_server_thread, (void*) context, 0, NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
CloseHandle(context->priv->StopEvent);
|
CloseHandle(context->priv->StopEvent);
|
||||||
@ -318,33 +327,30 @@ static UINT encomsp_server_start(EncomspServerContext* context)
|
|||||||
*/
|
*/
|
||||||
static UINT encomsp_server_stop(EncomspServerContext* context)
|
static UINT encomsp_server_stop(EncomspServerContext* context)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
SetEvent(context->priv->StopEvent);
|
SetEvent(context->priv->StopEvent);
|
||||||
|
|
||||||
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
|
if (WaitForSingleObject(context->priv->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(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)
|
||||||
|
@ -84,14 +84,12 @@ 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);
|
||||||
|
|
||||||
if (status < 1)
|
if (status < 1)
|
||||||
if (!(path = (char*) calloc(1, 1)))
|
if (!(path = (char*) calloc(1, 1)))
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,22 +373,22 @@ static UINT parallel_irp_request(DEVICE* device, IRP* irp)
|
|||||||
*/
|
*/
|
||||||
static UINT parallel_free(DEVICE* device)
|
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();
|
{
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
error = GetLastError();
|
||||||
return error;
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUILTIN_CHANNELS
|
#ifdef BUILTIN_CHANNELS
|
||||||
@ -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;
|
||||||
|
@ -58,14 +58,14 @@ static UINT rail_send(railPlugin* rail, wStream* s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = rail->channelEntryPoints.pVirtualChannelWrite(rail->OpenHandle,
|
status = rail->channelEntryPoints.pVirtualChannelWrite(rail->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -101,7 +101,7 @@ UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_execute(RailClientContext* context,
|
static UINT rail_client_execute(RailClientContext* context,
|
||||||
RAIL_EXEC_ORDER* exec)
|
RAIL_EXEC_ORDER* exec)
|
||||||
{
|
{
|
||||||
char* exeOrFile;
|
char* exeOrFile;
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
@ -117,11 +117,11 @@ static UINT rail_client_execute(RailClientContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rail_string_to_unicode_string(exec->RemoteApplicationProgram,
|
rail_string_to_unicode_string(exec->RemoteApplicationProgram,
|
||||||
&exec->exeOrFile); /* RemoteApplicationProgram */
|
&exec->exeOrFile); /* RemoteApplicationProgram */
|
||||||
rail_string_to_unicode_string(exec->RemoteApplicationWorkingDir,
|
rail_string_to_unicode_string(exec->RemoteApplicationWorkingDir,
|
||||||
&exec->workingDir); /* ShellWorkingDirectory */
|
&exec->workingDir); /* ShellWorkingDirectory */
|
||||||
rail_string_to_unicode_string(exec->RemoteApplicationArguments,
|
rail_string_to_unicode_string(exec->RemoteApplicationArguments,
|
||||||
&exec->arguments); /* RemoteApplicationCmdLine */
|
&exec->arguments); /* RemoteApplicationCmdLine */
|
||||||
return rail_send_client_exec_order(rail, exec);
|
return rail_send_client_exec_order(rail, exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ static UINT rail_client_execute(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_activate(RailClientContext* context,
|
static UINT rail_client_activate(RailClientContext* context,
|
||||||
RAIL_ACTIVATE_ORDER* activate)
|
RAIL_ACTIVATE_ORDER* activate)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_client_activate_order(rail, activate);
|
return rail_send_client_activate_order(rail, activate);
|
||||||
@ -143,7 +143,7 @@ static UINT rail_client_activate(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_send_client_sysparam(RailClientContext* context,
|
static UINT rail_send_client_sysparam(RailClientContext* context,
|
||||||
RAIL_SYSPARAM_ORDER* sysparam)
|
RAIL_SYSPARAM_ORDER* sysparam)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
int length;
|
int length;
|
||||||
@ -201,7 +201,7 @@ static UINT rail_send_client_sysparam(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_system_param(RailClientContext* context,
|
static UINT rail_client_system_param(RailClientContext* context,
|
||||||
RAIL_SYSPARAM_ORDER* sysparam)
|
RAIL_SYSPARAM_ORDER* sysparam)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
|
|
||||||
@ -291,7 +291,7 @@ static UINT rail_client_system_param(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_server_system_param(RailClientContext* context,
|
static UINT rail_server_system_param(RailClientContext* context,
|
||||||
RAIL_SYSPARAM_ORDER* sysparam)
|
RAIL_SYSPARAM_ORDER* sysparam)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||||
}
|
}
|
||||||
@ -302,7 +302,7 @@ static UINT rail_server_system_param(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_system_command(RailClientContext* context,
|
static UINT rail_client_system_command(RailClientContext* context,
|
||||||
RAIL_SYSCOMMAND_ORDER* syscommand)
|
RAIL_SYSCOMMAND_ORDER* syscommand)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_client_syscommand_order(rail, syscommand);
|
return rail_send_client_syscommand_order(rail, syscommand);
|
||||||
@ -314,7 +314,7 @@ static UINT rail_client_system_command(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_handshake(RailClientContext* context,
|
static UINT rail_client_handshake(RailClientContext* context,
|
||||||
RAIL_HANDSHAKE_ORDER* handshake)
|
RAIL_HANDSHAKE_ORDER* handshake)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_handshake_order(rail, handshake);
|
return rail_send_handshake_order(rail, handshake);
|
||||||
@ -326,7 +326,7 @@ static UINT rail_client_handshake(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_server_handshake(RailClientContext* context,
|
static UINT rail_server_handshake(RailClientContext* context,
|
||||||
RAIL_HANDSHAKE_ORDER* handshake)
|
RAIL_HANDSHAKE_ORDER* handshake)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||||
}
|
}
|
||||||
@ -337,7 +337,7 @@ static UINT rail_server_handshake(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_handshake_ex(RailClientContext* context,
|
static UINT rail_client_handshake_ex(RailClientContext* context,
|
||||||
RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_handshake_ex_order(rail, handshakeEx);
|
return rail_send_handshake_ex_order(rail, handshakeEx);
|
||||||
@ -349,7 +349,7 @@ static UINT rail_client_handshake_ex(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_server_handshake_ex(RailClientContext* context,
|
static UINT rail_server_handshake_ex(RailClientContext* context,
|
||||||
RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||||
}
|
}
|
||||||
@ -360,7 +360,7 @@ static UINT rail_server_handshake_ex(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_notify_event(RailClientContext* context,
|
static UINT rail_client_notify_event(RailClientContext* context,
|
||||||
RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
|
RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_client_notify_event_order(rail, notifyEvent);
|
return rail_send_client_notify_event_order(rail, notifyEvent);
|
||||||
@ -372,7 +372,7 @@ static UINT rail_client_notify_event(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_window_move(RailClientContext* context,
|
static UINT rail_client_window_move(RailClientContext* context,
|
||||||
RAIL_WINDOW_MOVE_ORDER* windowMove)
|
RAIL_WINDOW_MOVE_ORDER* windowMove)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_client_window_move_order(rail, windowMove);
|
return rail_send_client_window_move_order(rail, windowMove);
|
||||||
@ -384,7 +384,7 @@ static UINT rail_client_window_move(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_server_local_move_size(RailClientContext* context,
|
static UINT rail_server_local_move_size(RailClientContext* context,
|
||||||
RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
|
RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||||
}
|
}
|
||||||
@ -395,7 +395,7 @@ static UINT rail_server_local_move_size(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_server_min_max_info(RailClientContext* context,
|
static UINT rail_server_min_max_info(RailClientContext* context,
|
||||||
RAIL_MINMAXINFO_ORDER* minMaxInfo)
|
RAIL_MINMAXINFO_ORDER* minMaxInfo)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||||
}
|
}
|
||||||
@ -406,7 +406,7 @@ static UINT rail_server_min_max_info(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_information(RailClientContext* context,
|
static UINT rail_client_information(RailClientContext* context,
|
||||||
RAIL_CLIENT_STATUS_ORDER* clientStatus)
|
RAIL_CLIENT_STATUS_ORDER* clientStatus)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_client_status_order(rail, clientStatus);
|
return rail_send_client_status_order(rail, clientStatus);
|
||||||
@ -418,7 +418,7 @@ static UINT rail_client_information(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_system_menu(RailClientContext* context,
|
static UINT rail_client_system_menu(RailClientContext* context,
|
||||||
RAIL_SYSMENU_ORDER* sysmenu)
|
RAIL_SYSMENU_ORDER* sysmenu)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_client_sysmenu_order(rail, sysmenu);
|
return rail_send_client_sysmenu_order(rail, sysmenu);
|
||||||
@ -430,7 +430,7 @@ static UINT rail_client_system_menu(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_language_bar_info(RailClientContext* context,
|
static UINT rail_client_language_bar_info(RailClientContext* context,
|
||||||
RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_client_langbar_info_order(rail, langBarInfo);
|
return rail_send_client_langbar_info_order(rail, langBarInfo);
|
||||||
@ -442,7 +442,7 @@ static UINT rail_client_language_bar_info(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_server_language_bar_info(RailClientContext* context,
|
static UINT rail_server_language_bar_info(RailClientContext* context,
|
||||||
RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||||
}
|
}
|
||||||
@ -453,7 +453,7 @@ static UINT rail_server_language_bar_info(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_server_execute_result(RailClientContext* context,
|
static UINT rail_server_execute_result(RailClientContext* context,
|
||||||
RAIL_EXEC_RESULT_ORDER* execResult)
|
RAIL_EXEC_RESULT_ORDER* execResult)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||||
}
|
}
|
||||||
@ -464,7 +464,7 @@ static UINT rail_server_execute_result(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_client_get_appid_request(RailClientContext* context,
|
static UINT rail_client_get_appid_request(RailClientContext* context,
|
||||||
RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
|
RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
|
||||||
{
|
{
|
||||||
railPlugin* rail = (railPlugin*) context->handle;
|
railPlugin* rail = (railPlugin*) context->handle;
|
||||||
return rail_send_client_get_appid_req_order(rail, getAppIdReq);
|
return rail_send_client_get_appid_req_order(rail, getAppIdReq);
|
||||||
@ -476,7 +476,7 @@ static UINT rail_client_get_appid_request(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_server_get_appid_response(RailClientContext* context,
|
static UINT rail_server_get_appid_response(RailClientContext* context,
|
||||||
RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
|
RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||||
}
|
}
|
||||||
@ -487,7 +487,7 @@ static UINT rail_server_get_appid_response(RailClientContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_virtual_channel_event_data_received(railPlugin* rail,
|
static UINT rail_virtual_channel_event_data_received(railPlugin* rail,
|
||||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
wStream* data_in;
|
wStream* data_in;
|
||||||
|
|
||||||
@ -543,8 +543,8 @@ static UINT rail_virtual_channel_event_data_received(railPlugin* rail,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle,
|
static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle,
|
||||||
UINT event,
|
UINT event,
|
||||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
railPlugin* rail = s_TLSPluginContext;
|
railPlugin* rail = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -559,9 +559,9 @@ static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||||
if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength,
|
if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength,
|
||||||
totalLength, dataFlags)))
|
totalLength, dataFlags)))
|
||||||
WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!",
|
WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -575,7 +575,7 @@ static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle,
|
|||||||
|
|
||||||
if (error && rail->rdpcontext)
|
if (error && rail->rdpcontext)
|
||||||
setChannelError(rail->rdpcontext, error,
|
setChannelError(rail->rdpcontext, error,
|
||||||
"rail_virtual_channel_open_event reported an error");
|
"rail_virtual_channel_open_event reported an error");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -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))
|
||||||
@ -621,7 +621,7 @@ static void* rail_virtual_channel_client_thread(void* arg)
|
|||||||
|
|
||||||
if (error && rail->rdpcontext)
|
if (error && rail->rdpcontext)
|
||||||
setChannelError(rail->rdpcontext, error,
|
setChannelError(rail->rdpcontext, error,
|
||||||
"rail_virtual_channel_client_thread reported an error");
|
"rail_virtual_channel_client_thread reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD)error);
|
ExitThread((DWORD)error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -633,16 +633,16 @@ static void* rail_virtual_channel_client_thread(void* arg)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData,
|
static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData,
|
||||||
UINT32 dataLength)
|
UINT32 dataLength)
|
||||||
{
|
{
|
||||||
UINT status;
|
UINT status;
|
||||||
status = rail->channelEntryPoints.pVirtualChannelOpen(rail->InitHandle,
|
status = rail->channelEntryPoints.pVirtualChannelOpen(rail->InitHandle,
|
||||||
&rail->OpenHandle, rail->channelDef.name, rail_virtual_channel_open_event);
|
&rail->OpenHandle, rail->channelDef.name, rail_virtual_channel_open_event);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,8 +655,8 @@ static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(rail->thread = CreateThread(NULL, 0,
|
if (!(rail->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) rail_virtual_channel_client_thread, (void*) rail, 0,
|
(LPTHREAD_START_ROUTINE) rail_virtual_channel_client_thread, (void*) rail, 0,
|
||||||
NULL)))
|
NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
MessageQueue_Free(rail->queue);
|
MessageQueue_Free(rail->queue);
|
||||||
@ -693,7 +693,7 @@ static UINT rail_virtual_channel_event_disconnected(railPlugin* rail)
|
|||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,7 +715,7 @@ static void rail_virtual_channel_event_terminated(railPlugin* rail)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle,
|
static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle,
|
||||||
UINT event, LPVOID pData, UINT dataLength)
|
UINT event, LPVOID pData, UINT dataLength)
|
||||||
{
|
{
|
||||||
railPlugin* rail = s_TLSPluginContext;
|
railPlugin* rail = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -731,14 +731,14 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
case CHANNEL_EVENT_CONNECTED:
|
case CHANNEL_EVENT_CONNECTED:
|
||||||
if ((error = rail_virtual_channel_event_connected(rail, pData, dataLength)))
|
if ((error = rail_virtual_channel_event_connected(rail, pData, dataLength)))
|
||||||
WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!",
|
WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_DISCONNECTED:
|
case CHANNEL_EVENT_DISCONNECTED:
|
||||||
if ((error = rail_virtual_channel_event_disconnected(rail)))
|
if ((error = rail_virtual_channel_event_disconnected(rail)))
|
||||||
WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %lu!",
|
WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -749,7 +749,7 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
|
|
||||||
if (error && rail->rdpcontext)
|
if (error && rail->rdpcontext)
|
||||||
setChannelError(rail->rdpcontext, error,
|
setChannelError(rail->rdpcontext, error,
|
||||||
"rail_virtual_channel_init_event reported an error");
|
"rail_virtual_channel_init_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rail is always built-in */
|
/* rail is always built-in */
|
||||||
@ -822,15 +822,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
rail->log = WLog_Get("com.freerdp.channels.rail.client");
|
rail->log = WLog_Get("com.freerdp.channels.rail.client");
|
||||||
WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntry");
|
WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntry");
|
||||||
CopyMemory(&(rail->channelEntryPoints), pEntryPoints,
|
CopyMemory(&(rail->channelEntryPoints), pEntryPoints,
|
||||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||||
rc = rail->channelEntryPoints.pVirtualChannelInit(&rail->InitHandle,
|
rc = rail->channelEntryPoints.pVirtualChannelInit(&rail->InitHandle,
|
||||||
&rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
&rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||||
rail_virtual_channel_init_event);
|
rail_virtual_channel_init_event);
|
||||||
|
|
||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ static WINPR_TLS rdpdrPlugin* s_TLSPluginContext = NULL;
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
|
static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
|
||||||
BOOL userLoggedOn);
|
BOOL userLoggedOn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function description
|
* Function description
|
||||||
@ -91,7 +91,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr,
|
static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr,
|
||||||
UINT32 count, UINT32 ids[])
|
UINT32 count, UINT32 ids[])
|
||||||
{
|
{
|
||||||
UINT32 i;
|
UINT32 i;
|
||||||
wStream* s;
|
wStream* s;
|
||||||
@ -165,7 +165,7 @@ void first_hotplug(rdpdrPlugin* rdpdr)
|
|||||||
drive_path[1] = '\0';
|
drive_path[1] = '\0';
|
||||||
drive->Name = _strdup(drive_path);
|
drive->Name = _strdup(drive_path);
|
||||||
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive,
|
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive,
|
||||||
rdpdr->rdpcontext);
|
rdpdr->rdpcontext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|||||||
drive_path[1] = '\0';
|
drive_path[1] = '\0';
|
||||||
drive->Name = _strdup(drive_path);
|
drive->Name = _strdup(drive_path);
|
||||||
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive,
|
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive,
|
||||||
rdpdr->rdpcontext);
|
rdpdr->rdpcontext);
|
||||||
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
|
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,7 +243,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|||||||
for (j = 0; j < count; j++)
|
for (j = 0; j < count; j++)
|
||||||
{
|
{
|
||||||
device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(
|
device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(
|
||||||
rdpdr->devman->devices, (void*)keys[j]);
|
rdpdr->devman->devices, (void*)keys[j]);
|
||||||
|
|
||||||
if (device_ext->path[0] == drive_name_upper
|
if (device_ext->path[0] == drive_name_upper
|
||||||
|| device_ext->path[0] == drive_name_lower)
|
|| device_ext->path[0] == drive_name_lower)
|
||||||
@ -255,7 +255,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|||||||
{
|
{
|
||||||
// dont end on error, just report ?
|
// dont end on error, just report ?
|
||||||
WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!",
|
WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -308,15 +308,15 @@ static void* drive_hotplug_thread_func(void* arg)
|
|||||||
RegisterClassEx(&wnd_cls);
|
RegisterClassEx(&wnd_cls);
|
||||||
/* create window */
|
/* create window */
|
||||||
hwnd = CreateWindowEx(0, L"DRIVE_HOTPLUG", NULL,
|
hwnd = CreateWindowEx(0, L"DRIVE_HOTPLUG", NULL,
|
||||||
0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0,
|
||||||
NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)rdpdr);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)rdpdr);
|
||||||
rdpdr->hotplug_wnd = hwnd;
|
rdpdr->hotplug_wnd = hwnd;
|
||||||
/* register device interface to hwnd */
|
/* register device interface to hwnd */
|
||||||
NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
|
NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
|
||||||
NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
|
NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
|
||||||
hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter,
|
hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter,
|
||||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
|
|
||||||
/* message loop */
|
/* message loop */
|
||||||
while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
|
while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
|
||||||
@ -424,7 +424,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
|||||||
{
|
{
|
||||||
BOOL dev_found = FALSE;
|
BOOL dev_found = FALSE;
|
||||||
device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(
|
device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(
|
||||||
rdpdr->devman->devices, (void*)keys[j]);
|
rdpdr->devman->devices, (void*)keys[j]);
|
||||||
|
|
||||||
if (!device_ext)
|
if (!device_ext)
|
||||||
continue;
|
continue;
|
||||||
@ -454,7 +454,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
|||||||
if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids)))
|
if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!",
|
WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,7 +493,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive,
|
if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive,
|
||||||
rdpdr->rdpcontext)))
|
rdpdr->rdpcontext)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "devman_load_device_service failed!");
|
WLog_ERR(TAG, "devman_load_device_service failed!");
|
||||||
free(drive->Path);
|
free(drive->Path);
|
||||||
@ -515,9 +515,9 @@ cleanup:
|
|||||||
|
|
||||||
|
|
||||||
static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef,
|
static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef,
|
||||||
void* clientCallBackInfo,
|
void* clientCallBackInfo,
|
||||||
size_t numEvents, void* eventPaths, const FSEventStreamEventFlags eventFlags[],
|
size_t numEvents, void* eventPaths, const FSEventStreamEventFlags eventFlags[],
|
||||||
const FSEventStreamEventId eventIds[])
|
const FSEventStreamEventId eventIds[])
|
||||||
{
|
{
|
||||||
rdpdrPlugin* rdpdr;
|
rdpdrPlugin* rdpdr;
|
||||||
int i;
|
int i;
|
||||||
@ -558,13 +558,13 @@ static void* drive_hotplug_thread_func(void* arg)
|
|||||||
rdpdr = (rdpdrPlugin*) arg;
|
rdpdr = (rdpdrPlugin*) arg;
|
||||||
CFStringRef path = CFSTR("/Volumes/");
|
CFStringRef path = CFSTR("/Volumes/");
|
||||||
CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorMalloc, (const void**)&path,
|
CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorMalloc, (const void**)&path,
|
||||||
1, NULL);
|
1, NULL);
|
||||||
FSEventStreamContext ctx;
|
FSEventStreamContext ctx;
|
||||||
ZeroMemory(&ctx, sizeof(ctx));
|
ZeroMemory(&ctx, sizeof(ctx));
|
||||||
ctx.info = arg;
|
ctx.info = arg;
|
||||||
fsev = FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback,
|
fsev = FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback,
|
||||||
&ctx, pathsToWatch, kFSEventStreamEventIdSinceNow, 1,
|
&ctx, pathsToWatch, kFSEventStreamEventIdSinceNow, 1,
|
||||||
kFSEventStreamCreateFlagNone);
|
kFSEventStreamCreateFlagNone);
|
||||||
rdpdr->runLoop = CFRunLoopGetCurrent();
|
rdpdr->runLoop = CFRunLoopGetCurrent();
|
||||||
FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode);
|
FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode);
|
||||||
FSEventStreamStart(fsev);
|
FSEventStreamStart(fsev);
|
||||||
@ -758,7 +758,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
|||||||
{
|
{
|
||||||
BOOL dev_found = FALSE;
|
BOOL dev_found = FALSE;
|
||||||
device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(
|
device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(
|
||||||
rdpdr->devman->devices, (void*)keys[j]);
|
rdpdr->devman->devices, (void*)keys[j]);
|
||||||
|
|
||||||
if (!device_ext || !device_ext->path)
|
if (!device_ext || !device_ext->path)
|
||||||
continue;
|
continue;
|
||||||
@ -786,7 +786,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
|||||||
if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids)))
|
if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!",
|
WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -825,7 +825,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive,
|
if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive,
|
||||||
rdpdr->rdpcontext)))
|
rdpdr->rdpcontext)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "devman_load_device_service failed!");
|
WLog_ERR(TAG, "devman_load_device_service failed!");
|
||||||
free(drive->Path);
|
free(drive->Path);
|
||||||
@ -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!");
|
||||||
@ -923,7 +923,7 @@ out:
|
|||||||
|
|
||||||
if (error && rdpdr->rdpcontext)
|
if (error && rdpdr->rdpcontext)
|
||||||
setChannelError(rdpdr->rdpcontext, error,
|
setChannelError(rdpdr->rdpcontext, error,
|
||||||
"drive_hotplug_thread_func reported an error");
|
"drive_hotplug_thread_func reported an error");
|
||||||
|
|
||||||
CloseHandle(rdpdr->stopEvent);
|
CloseHandle(rdpdr->stopEvent);
|
||||||
ExitThread((DWORD)error);
|
ExitThread((DWORD)error);
|
||||||
@ -983,10 +983,10 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
|||||||
|
|
||||||
if (settings->ClientHostname)
|
if (settings->ClientHostname)
|
||||||
strncpy(rdpdr->computerName, settings->ClientHostname,
|
strncpy(rdpdr->computerName, settings->ClientHostname,
|
||||||
sizeof(rdpdr->computerName) - 1);
|
sizeof(rdpdr->computerName) - 1);
|
||||||
else
|
else
|
||||||
strncpy(rdpdr->computerName, settings->ComputerName,
|
strncpy(rdpdr->computerName, settings->ComputerName,
|
||||||
sizeof(rdpdr->computerName) - 1);
|
sizeof(rdpdr->computerName) - 1);
|
||||||
|
|
||||||
for (index = 0; index < settings->DeviceCount; index++)
|
for (index = 0; index < settings->DeviceCount; index++)
|
||||||
{
|
{
|
||||||
@ -997,7 +997,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
|||||||
first_hotplug(rdpdr);
|
first_hotplug(rdpdr);
|
||||||
|
|
||||||
if (!(rdpdr->hotplugThread = CreateThread(NULL, 0,
|
if (!(rdpdr->hotplugThread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) drive_hotplug_thread_func, rdpdr, 0, NULL)))
|
(LPTHREAD_START_ROUTINE) drive_hotplug_thread_func, rdpdr, 0, NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
@ -1007,7 +1007,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((error = devman_load_device_service(rdpdr->devman, device,
|
if ((error = devman_load_device_service(rdpdr->devman, device,
|
||||||
rdpdr->rdpcontext)))
|
rdpdr->rdpcontext)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "devman_load_device_service failed with error %lu!", error);
|
WLog_ERR(TAG, "devman_load_device_service failed with error %lu!", error);
|
||||||
return error;
|
return error;
|
||||||
@ -1018,7 +1018,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static UINT rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr,
|
static UINT rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
if (Stream_GetRemainingLength(s) < 8)
|
if (Stream_GetRemainingLength(s) < 8)
|
||||||
return ERROR_INVALID_DATA;
|
return ERROR_INVALID_DATA;
|
||||||
@ -1069,7 +1069,7 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
|
|||||||
gethostname(rdpdr->computerName, sizeof(rdpdr->computerName) - 1);
|
gethostname(rdpdr->computerName, sizeof(rdpdr->computerName) - 1);
|
||||||
|
|
||||||
computerNameLenW = ConvertToUnicode(CP_UTF8, 0, rdpdr->computerName, -1,
|
computerNameLenW = ConvertToUnicode(CP_UTF8, 0, rdpdr->computerName, -1,
|
||||||
&computerNameW, 0) * 2;
|
&computerNameW, 0) * 2;
|
||||||
s = Stream_New(NULL, 16 + computerNameLenW + 2);
|
s = Stream_New(NULL, 16 + computerNameLenW + 2);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
@ -1083,7 +1083,7 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
|
|||||||
Stream_Write_UINT32(s, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */
|
Stream_Write_UINT32(s, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */
|
||||||
Stream_Write_UINT32(s, 0); /* codePage, must be set to zero */
|
Stream_Write_UINT32(s, 0); /* codePage, must be set to zero */
|
||||||
Stream_Write_UINT32(s, computerNameLenW +
|
Stream_Write_UINT32(s, computerNameLenW +
|
||||||
2); /* computerNameLen, including null terminator */
|
2); /* computerNameLen, including null terminator */
|
||||||
Stream_Write(s, computerNameW, computerNameLenW);
|
Stream_Write(s, computerNameW, computerNameLenW);
|
||||||
Stream_Write_UINT16(s, 0); /* null terminator */
|
Stream_Write_UINT16(s, 0); /* null terminator */
|
||||||
free(computerNameW);
|
free(computerNameW);
|
||||||
@ -1091,7 +1091,7 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr,
|
static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
UINT16 versionMajor;
|
UINT16 versionMajor;
|
||||||
UINT16 versionMinor;
|
UINT16 versionMinor;
|
||||||
@ -1122,7 +1122,7 @@ static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
|
static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
|
||||||
BOOL userLoggedOn)
|
BOOL userLoggedOn)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
BYTE c;
|
BYTE c;
|
||||||
@ -1154,7 +1154,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
|
|||||||
for (index = 0; index < keyCount; index++)
|
for (index = 0; index < keyCount; index++)
|
||||||
{
|
{
|
||||||
device = (DEVICE*) ListDictionary_GetItemValue(rdpdr->devman->devices,
|
device = (DEVICE*) ListDictionary_GetItemValue(rdpdr->devman->devices,
|
||||||
(void*) pKeys[index]);
|
(void*) pKeys[index]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON
|
* 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON
|
||||||
@ -1195,7 +1195,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
|
|||||||
|
|
||||||
count++;
|
count++;
|
||||||
WLog_INFO(TAG, "registered device #%d: %s (type=%d id=%d)",
|
WLog_INFO(TAG, "registered device #%d: %s (type=%d id=%d)",
|
||||||
count, device->name, device->type, device->id);
|
count, device->name, device->type, device->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,7 +1251,7 @@ static UINT rdpdr_process_init(rdpdrPlugin* rdpdr)
|
|||||||
for (index = 0; index < keyCount; index++)
|
for (index = 0; index < keyCount; index++)
|
||||||
{
|
{
|
||||||
device = (DEVICE*) ListDictionary_GetItemValue(rdpdr->devman->devices,
|
device = (DEVICE*) ListDictionary_GetItemValue(rdpdr->devman->devices,
|
||||||
(void*) pKeys[index]);
|
(void*) pKeys[index]);
|
||||||
IFCALLRET(device->Init, error, device);
|
IFCALLRET(device->Init, error, device);
|
||||||
|
|
||||||
if (error != CHANNEL_RC_OK)
|
if (error != CHANNEL_RC_OK)
|
||||||
@ -1335,7 +1335,7 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
|
|||||||
if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE)))
|
if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu",
|
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1345,7 +1345,7 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
|
|||||||
if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE)))
|
if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu",
|
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1390,7 +1390,7 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
|
|||||||
|
|
||||||
Stream_Read_UINT32(s, eventID);
|
Stream_Read_UINT32(s, eventID);
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%04X)", eventID);
|
"Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%04X)", eventID);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1406,7 +1406,7 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Unknown message: Component: 0x%04X PacketId: 0x%04X", component,
|
WLog_ERR(TAG, "Unknown message: Component: 0x%04X PacketId: 0x%04X", component,
|
||||||
packetId);
|
packetId);
|
||||||
return ERROR_INVALID_DATA;
|
return ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1432,14 +1432,14 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
|
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -1451,7 +1451,7 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr,
|
static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr,
|
||||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
wStream* data_in;
|
wStream* data_in;
|
||||||
|
|
||||||
@ -1513,8 +1513,8 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle,
|
static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle,
|
||||||
UINT event,
|
UINT event,
|
||||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
rdpdrPlugin* rdpdr = s_TLSPluginContext;
|
rdpdrPlugin* rdpdr = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1529,9 +1529,9 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||||
if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData,
|
if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData,
|
||||||
dataLength, totalLength, dataFlags)))
|
dataLength, totalLength, dataFlags)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"rdpdr_virtual_channel_event_data_received failed with error %lu!", error);
|
"rdpdr_virtual_channel_event_data_received failed with error %lu!", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1545,7 +1545,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle,
|
|||||||
|
|
||||||
if (error && rdpdr->rdpcontext)
|
if (error && rdpdr->rdpcontext)
|
||||||
setChannelError(rdpdr->rdpcontext, error,
|
setChannelError(rdpdr->rdpcontext, error,
|
||||||
"rdpdr_virtual_channel_open_event reported an error");
|
"rdpdr_virtual_channel_open_event reported an error");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1565,13 +1565,14 @@ 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);
|
||||||
|
|
||||||
if (rdpdr->rdpcontext)
|
if (rdpdr->rdpcontext)
|
||||||
setChannelError(rdpdr->rdpcontext, error,
|
setChannelError(rdpdr->rdpcontext, error,
|
||||||
"rdpdr_virtual_channel_client_thread reported an error");
|
"rdpdr_virtual_channel_client_thread reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD) error);
|
ExitThread((DWORD) error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1597,7 +1598,7 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
|
|||||||
|
|
||||||
if (rdpdr->rdpcontext)
|
if (rdpdr->rdpcontext)
|
||||||
setChannelError(rdpdr->rdpcontext, error,
|
setChannelError(rdpdr->rdpcontext, error,
|
||||||
"rdpdr_virtual_channel_client_thread reported an error");
|
"rdpdr_virtual_channel_client_thread reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD) error);
|
ExitThread((DWORD) error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1616,16 +1617,16 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr,
|
static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr,
|
||||||
LPVOID pData, UINT32 dataLength)
|
LPVOID pData, UINT32 dataLength)
|
||||||
{
|
{
|
||||||
UINT32 status;
|
UINT32 status;
|
||||||
status = rdpdr->channelEntryPoints.pVirtualChannelOpen(rdpdr->InitHandle,
|
status = rdpdr->channelEntryPoints.pVirtualChannelOpen(rdpdr->InitHandle,
|
||||||
&rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event);
|
&rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1638,8 +1639,8 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(rdpdr->thread = CreateThread(NULL, 0,
|
if (!(rdpdr->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0,
|
(LPTHREAD_START_ROUTINE) rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0,
|
||||||
NULL)))
|
NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
@ -1681,7 +1682,7 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr)
|
|||||||
if (CHANNEL_RC_OK != error)
|
if (CHANNEL_RC_OK != error)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||||
WTSErrorToString(error), error);
|
WTSErrorToString(error), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpdr->OpenHandle = 0;
|
rdpdr->OpenHandle = 0;
|
||||||
@ -1707,8 +1708,8 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle,
|
static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle,
|
||||||
UINT event,
|
UINT event,
|
||||||
LPVOID pData, UINT dataLength)
|
LPVOID pData, UINT dataLength)
|
||||||
{
|
{
|
||||||
rdpdrPlugin* rdpdr = s_TLSPluginContext;
|
rdpdrPlugin* rdpdr = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1727,14 +1728,14 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
case CHANNEL_EVENT_CONNECTED:
|
case CHANNEL_EVENT_CONNECTED:
|
||||||
if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength)))
|
if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength)))
|
||||||
WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!",
|
WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_DISCONNECTED:
|
case CHANNEL_EVENT_DISCONNECTED:
|
||||||
if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr)))
|
if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr)))
|
||||||
WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!",
|
WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1750,7 +1751,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
|
|
||||||
if (error && rdpdr->rdpcontext)
|
if (error && rdpdr->rdpcontext)
|
||||||
setChannelError(rdpdr->rdpcontext, error,
|
setChannelError(rdpdr->rdpcontext, error,
|
||||||
"rdpdr_virtual_channel_init_event reported an error");
|
"rdpdr_virtual_channel_init_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rdpdr is always built-in */
|
/* rdpdr is always built-in */
|
||||||
@ -1784,15 +1785,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints,
|
CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints,
|
||||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||||
rc = rdpdr->channelEntryPoints.pVirtualChannelInit(&rdpdr->InitHandle,
|
rc = rdpdr->channelEntryPoints.pVirtualChannelInit(&rdpdr->InitHandle,
|
||||||
&rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
&rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||||
rdpdr_virtual_channel_init_event);
|
rdpdr_virtual_channel_init_event);
|
||||||
|
|
||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
free(rdpdr);
|
free(rdpdr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
@ -194,12 +194,12 @@ static void* rdpei_schedule_thread(void* arg)
|
|||||||
{
|
{
|
||||||
status = WaitForMultipleObjects(2, hdl, FALSE, 20);
|
status = WaitForMultipleObjects(2, hdl, FALSE, 20);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
if (status == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0 + 1)
|
if (status == WAIT_OBJECT_0 + 1)
|
||||||
break;
|
break;
|
||||||
@ -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,13 +504,11 @@ 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);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
@ -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*
|
||||||
IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept,
|
pListenerCallback,
|
||||||
IWTSVirtualChannelCallback** ppCallback)
|
IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept,
|
||||||
|
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,52 +613,52 @@ 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;
|
||||||
|
|
||||||
if ((error = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0,
|
if ((error = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0,
|
||||||
(IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener))))
|
(IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener))))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %lu!", error);
|
WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %lu!", error);
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
rdpei_schedule_thread, (void*) rdpei, 0, NULL)))
|
rdpei_schedule_thread, (void*) rdpei, 0, NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
goto error_out;
|
goto error_out;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
@ -691,7 +677,7 @@ error_out:
|
|||||||
static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin)
|
static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin)
|
||||||
{
|
{
|
||||||
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin;
|
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin;
|
||||||
UINT error;
|
UINT error;
|
||||||
|
|
||||||
if (!pPlugin)
|
if (!pPlugin)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
@ -700,22 +686,19 @@ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin)
|
|||||||
EnterCriticalSection(&rdpei->lock);
|
EnterCriticalSection(&rdpei->lock);
|
||||||
|
|
||||||
if (WaitForSingleObject(rdpei->thread, INFINITE) == WAIT_FAILED)
|
if (WaitForSingleObject(rdpei->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(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;
|
||||||
|
@ -55,7 +55,7 @@ static INLINE UINT32 rdpgfx_pdu_length(UINT32 dataLen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static INLINE UINT rdpgfx_server_packet_init_header(wStream* s,
|
static INLINE UINT rdpgfx_server_packet_init_header(wStream* s,
|
||||||
UINT16 cmdId, UINT32 pduLength)
|
UINT16 cmdId, UINT32 pduLength)
|
||||||
{
|
{
|
||||||
RDPGFX_HEADER header;
|
RDPGFX_HEADER header;
|
||||||
header.flags = 0;
|
header.flags = 0;
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
@ -111,7 +112,7 @@ static UINT rdpgfx_server_packet_send(RdpgfxServerContext* context, wStream* s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (zgfx_compress_to_stream(context->priv->zgfx, fs, pSrcData,
|
if (zgfx_compress_to_stream(context->priv->zgfx, fs, pSrcData,
|
||||||
SrcSize, &flags) < 0)
|
SrcSize, &flags) < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "zgfx_compress_to_stream failed!");
|
WLog_ERR(TAG, "zgfx_compress_to_stream failed!");
|
||||||
error = ERROR_INTERNAL_ERROR;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
@ -119,8 +120,8 @@ static UINT rdpgfx_server_packet_send(RdpgfxServerContext* context, wStream* s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!WTSVirtualChannelWrite(context->priv->rdpgfx_channel,
|
if (!WTSVirtualChannelWrite(context->priv->rdpgfx_channel,
|
||||||
(PCHAR) Stream_Buffer(fs),
|
(PCHAR) Stream_Buffer(fs),
|
||||||
Stream_GetPosition(fs), &written))
|
Stream_GetPosition(fs), &written))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
|
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
|
||||||
error = ERROR_INTERNAL_ERROR;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
@ -130,7 +131,7 @@ static UINT rdpgfx_server_packet_send(RdpgfxServerContext* context, wStream* s)
|
|||||||
if (written < Stream_GetPosition(fs))
|
if (written < Stream_GetPosition(fs))
|
||||||
{
|
{
|
||||||
WLog_WARN(TAG, "Unexpected bytes written: %lu/%lu",
|
WLog_WARN(TAG, "Unexpected bytes written: %lu/%lu",
|
||||||
written, Stream_GetPosition(fs));
|
written, Stream_GetPosition(fs));
|
||||||
}
|
}
|
||||||
|
|
||||||
error = CHANNEL_RC_OK;
|
error = CHANNEL_RC_OK;
|
||||||
@ -186,7 +187,7 @@ error:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static INLINE UINT rdpgfx_server_single_packet_send(
|
static INLINE UINT rdpgfx_server_single_packet_send(
|
||||||
RdpgfxServerContext* context, wStream* s)
|
RdpgfxServerContext* context, wStream* s)
|
||||||
{
|
{
|
||||||
/* Fill actual length */
|
/* Fill actual length */
|
||||||
rdpgfx_server_packet_complete_header(s, 0);
|
rdpgfx_server_packet_complete_header(s, 0);
|
||||||
@ -199,11 +200,11 @@ static INLINE UINT rdpgfx_server_single_packet_send(
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_caps_confirm_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_caps_confirm_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_CAPS_CONFIRM_PDU* capsConfirm)
|
RDPGFX_CAPS_CONFIRM_PDU* capsConfirm)
|
||||||
{
|
{
|
||||||
RDPGFX_CAPSET* capsSet = capsConfirm->capsSet;
|
RDPGFX_CAPSET* capsSet = capsConfirm->capsSet;
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_CAPSCONFIRM, RDPGFX_CAPSET_SIZE);
|
RDPGFX_CMDID_CAPSCONFIRM, RDPGFX_CAPSET_SIZE);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -223,7 +224,7 @@ static UINT rdpgfx_send_caps_confirm_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_reset_graphics_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_reset_graphics_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_RESET_GRAPHICS_PDU* pdu)
|
RDPGFX_RESET_GRAPHICS_PDU* pdu)
|
||||||
{
|
{
|
||||||
UINT32 index;
|
UINT32 index;
|
||||||
MONITOR_DEF* monitor;
|
MONITOR_DEF* monitor;
|
||||||
@ -233,13 +234,13 @@ static UINT rdpgfx_send_reset_graphics_pdu(RdpgfxServerContext* context,
|
|||||||
if (pdu->monitorCount >= 16)
|
if (pdu->monitorCount >= 16)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Monitor count MUST be less than or equal to 16: %lu",
|
WLog_ERR(TAG, "Monitor count MUST be less than or equal to 16: %lu",
|
||||||
pdu->monitorCount);
|
pdu->monitorCount);
|
||||||
return ERROR_INVALID_DATA;
|
return ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = rdpgfx_server_single_packet_new(
|
s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_RESETGRAPHICS,
|
RDPGFX_CMDID_RESETGRAPHICS,
|
||||||
RDPGFX_RESET_GRAPHICS_PDU_SIZE - RDPGFX_HEADER_SIZE);
|
RDPGFX_RESET_GRAPHICS_PDU_SIZE - RDPGFX_HEADER_SIZE);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -272,7 +273,7 @@ static UINT rdpgfx_send_reset_graphics_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_evict_cache_entry_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_evict_cache_entry_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_EVICT_CACHE_ENTRY_PDU* pdu)
|
RDPGFX_EVICT_CACHE_ENTRY_PDU* pdu)
|
||||||
{
|
{
|
||||||
wStream* s = rdpgfx_server_single_packet_new(RDPGFX_CMDID_EVICTCACHEENTRY, 2);
|
wStream* s = rdpgfx_server_single_packet_new(RDPGFX_CMDID_EVICTCACHEENTRY, 2);
|
||||||
|
|
||||||
@ -292,12 +293,12 @@ static UINT rdpgfx_send_evict_cache_entry_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_cache_import_reply_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_cache_import_reply_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_CACHE_IMPORT_REPLY_PDU* pdu)
|
RDPGFX_CACHE_IMPORT_REPLY_PDU* pdu)
|
||||||
{
|
{
|
||||||
UINT16 index;
|
UINT16 index;
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_CACHEIMPORTREPLY,
|
RDPGFX_CMDID_CACHEIMPORTREPLY,
|
||||||
2 + 2 * pdu->importedEntriesCount);
|
2 + 2 * pdu->importedEntriesCount);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -322,7 +323,7 @@ static UINT rdpgfx_send_cache_import_reply_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_create_surface_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_create_surface_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_CREATE_SURFACE_PDU* pdu)
|
RDPGFX_CREATE_SURFACE_PDU* pdu)
|
||||||
{
|
{
|
||||||
wStream* s = rdpgfx_server_single_packet_new(RDPGFX_CMDID_CREATESURFACE, 7);
|
wStream* s = rdpgfx_server_single_packet_new(RDPGFX_CMDID_CREATESURFACE, 7);
|
||||||
|
|
||||||
@ -345,7 +346,7 @@ static UINT rdpgfx_send_create_surface_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
UINT rdpgfx_send_delete_surface_pdu(RdpgfxServerContext* context,
|
UINT rdpgfx_send_delete_surface_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_DELETE_SURFACE_PDU* pdu)
|
RDPGFX_DELETE_SURFACE_PDU* pdu)
|
||||||
{
|
{
|
||||||
wStream* s = rdpgfx_server_single_packet_new(RDPGFX_CMDID_DELETESURFACE, 2);
|
wStream* s = rdpgfx_server_single_packet_new(RDPGFX_CMDID_DELETESURFACE, 2);
|
||||||
|
|
||||||
@ -360,14 +361,14 @@ UINT rdpgfx_send_delete_surface_pdu(RdpgfxServerContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static INLINE void rdpgfx_write_start_frame_pdu(wStream* s,
|
static INLINE void rdpgfx_write_start_frame_pdu(wStream* s,
|
||||||
RDPGFX_START_FRAME_PDU* pdu)
|
RDPGFX_START_FRAME_PDU* pdu)
|
||||||
{
|
{
|
||||||
Stream_Write_UINT32(s, pdu->timestamp); /* timestamp (4 bytes) */
|
Stream_Write_UINT32(s, pdu->timestamp); /* timestamp (4 bytes) */
|
||||||
Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */
|
Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE void rdpgfx_write_end_frame_pdu(wStream* s,
|
static INLINE void rdpgfx_write_end_frame_pdu(wStream* s,
|
||||||
RDPGFX_END_FRAME_PDU* pdu)
|
RDPGFX_END_FRAME_PDU* pdu)
|
||||||
{
|
{
|
||||||
Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */
|
Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */
|
||||||
}
|
}
|
||||||
@ -378,11 +379,11 @@ static INLINE void rdpgfx_write_end_frame_pdu(wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_start_frame_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_start_frame_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_START_FRAME_PDU* pdu)
|
RDPGFX_START_FRAME_PDU* pdu)
|
||||||
{
|
{
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_STARTFRAME,
|
RDPGFX_CMDID_STARTFRAME,
|
||||||
RDPGFX_START_FRAME_PDU_SIZE);
|
RDPGFX_START_FRAME_PDU_SIZE);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -400,11 +401,11 @@ static UINT rdpgfx_send_start_frame_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_end_frame_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_end_frame_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_END_FRAME_PDU* pdu)
|
RDPGFX_END_FRAME_PDU* pdu)
|
||||||
{
|
{
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_ENDFRAME,
|
RDPGFX_CMDID_ENDFRAME,
|
||||||
RDPGFX_END_FRAME_PDU_SIZE);
|
RDPGFX_END_FRAME_PDU_SIZE);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -423,13 +424,13 @@ static UINT rdpgfx_send_end_frame_pdu(RdpgfxServerContext* context,
|
|||||||
* @return estimated size
|
* @return estimated size
|
||||||
*/
|
*/
|
||||||
static INLINE UINT32 rdpgfx_estimate_h264_avc420(
|
static INLINE UINT32 rdpgfx_estimate_h264_avc420(
|
||||||
RDPGFX_AVC420_BITMAP_STREAM* havc420)
|
RDPGFX_AVC420_BITMAP_STREAM* havc420)
|
||||||
{
|
{
|
||||||
/* H264 metadata + H264 stream. See rdpgfx_write_h264_avc420 */
|
/* H264 metadata + H264 stream. See rdpgfx_write_h264_avc420 */
|
||||||
return sizeof(UINT32) /* numRegionRects */
|
return sizeof(UINT32) /* numRegionRects */
|
||||||
+ 10 /* regionRects + quantQualityVals */
|
+ 10 /* regionRects + quantQualityVals */
|
||||||
* havc420->meta.numRegionRects
|
* havc420->meta.numRegionRects
|
||||||
+ havc420->length;
|
+ havc420->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
@ -484,7 +489,7 @@ static INLINE UINT32 rdpgfx_estimate_surface_command(RDPGFX_SURFACE_COMMAND* cmd
|
|||||||
static INLINE UINT16 rdpgfx_surface_command_cmdid(RDPGFX_SURFACE_COMMAND* cmd)
|
static INLINE UINT16 rdpgfx_surface_command_cmdid(RDPGFX_SURFACE_COMMAND* cmd)
|
||||||
{
|
{
|
||||||
if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
|
if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
|
||||||
cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
|
cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
|
||||||
{
|
{
|
||||||
return RDPGFX_CMDID_WIRETOSURFACE_2;
|
return RDPGFX_CMDID_WIRETOSURFACE_2;
|
||||||
}
|
}
|
||||||
@ -520,8 +525,8 @@ static UINT rdpgfx_write_h264_metablock(wStream* s, RDPGFX_H264_METABLOCK* meta)
|
|||||||
{
|
{
|
||||||
quantQualityVal = &(meta->quantQualityVals[index]);
|
quantQualityVal = &(meta->quantQualityVals[index]);
|
||||||
Stream_Write_UINT8(s, quantQualityVal->qp
|
Stream_Write_UINT8(s, quantQualityVal->qp
|
||||||
| (quantQualityVal->r << 6)
|
| (quantQualityVal->r << 6)
|
||||||
| (quantQualityVal->p << 7)); /* qpVal (1 byte) */
|
| (quantQualityVal->p << 7)); /* qpVal (1 byte) */
|
||||||
/* qualityVal (1 byte) */
|
/* qualityVal (1 byte) */
|
||||||
Stream_Write_UINT8(s, quantQualityVal->qualityVal);
|
Stream_Write_UINT8(s, quantQualityVal->qualityVal);
|
||||||
}
|
}
|
||||||
@ -536,14 +541,14 @@ static UINT rdpgfx_write_h264_metablock(wStream* s, RDPGFX_H264_METABLOCK* meta)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static INLINE UINT rdpgfx_write_h264_avc420(wStream* s,
|
static INLINE UINT rdpgfx_write_h264_avc420(wStream* s,
|
||||||
RDPGFX_AVC420_BITMAP_STREAM* havc420)
|
RDPGFX_AVC420_BITMAP_STREAM* havc420)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
|
|
||||||
if ((error = rdpgfx_write_h264_metablock(s, &(havc420->meta))))
|
if ((error = rdpgfx_write_h264_metablock(s, &(havc420->meta))))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdpgfx_write_h264_metablock failed with error %lu!",
|
WLog_ERR(TAG, "rdpgfx_write_h264_metablock failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
||||||
@ -567,7 +573,7 @@ static UINT rdpgfx_write_surface_command(wStream* s, RDPGFX_SURFACE_COMMAND* cmd
|
|||||||
UINT32 bitmapDataLength = 0;
|
UINT32 bitmapDataLength = 0;
|
||||||
|
|
||||||
if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
|
if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
|
||||||
cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
|
cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
|
||||||
{
|
{
|
||||||
/* Write RDPGFX_CMDID_WIRETOSURFACE_2 format for CAPROGRESSIVE */
|
/* Write RDPGFX_CMDID_WIRETOSURFACE_2 format for CAPROGRESSIVE */
|
||||||
Stream_Write_UINT16(s, cmd->surfaceId); /* surfaceId (2 bytes) */
|
Stream_Write_UINT16(s, cmd->surfaceId); /* surfaceId (2 bytes) */
|
||||||
@ -653,13 +659,13 @@ static UINT rdpgfx_write_surface_command(wStream* s, RDPGFX_SURFACE_COMMAND* cmd
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_surface_command(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_surface_command(RdpgfxServerContext* context,
|
||||||
RDPGFX_SURFACE_COMMAND* cmd)
|
RDPGFX_SURFACE_COMMAND* cmd)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
wStream* s;
|
wStream* s;
|
||||||
s = rdpgfx_server_single_packet_new(
|
s = rdpgfx_server_single_packet_new(
|
||||||
rdpgfx_surface_command_cmdid(cmd),
|
rdpgfx_surface_command_cmdid(cmd),
|
||||||
rdpgfx_estimate_surface_command(cmd));
|
rdpgfx_estimate_surface_command(cmd));
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -690,8 +696,8 @@ error:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
|
||||||
RDPGFX_SURFACE_COMMAND* cmd, RDPGFX_START_FRAME_PDU* startFrame,
|
RDPGFX_SURFACE_COMMAND* cmd, RDPGFX_START_FRAME_PDU* startFrame,
|
||||||
RDPGFX_END_FRAME_PDU* endFrame)
|
RDPGFX_END_FRAME_PDU* endFrame)
|
||||||
|
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -722,7 +728,7 @@ static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
|
|||||||
{
|
{
|
||||||
position = Stream_GetPosition(s);
|
position = Stream_GetPosition(s);
|
||||||
error = rdpgfx_server_packet_init_header(s,
|
error = rdpgfx_server_packet_init_header(s,
|
||||||
RDPGFX_CMDID_STARTFRAME, 0);
|
RDPGFX_CMDID_STARTFRAME, 0);
|
||||||
|
|
||||||
if (error != CHANNEL_RC_OK)
|
if (error != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
@ -737,8 +743,8 @@ static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
|
|||||||
/* Write RDPGFX_CMDID_WIRETOSURFACE_1 or RDPGFX_CMDID_WIRETOSURFACE_2 */
|
/* Write RDPGFX_CMDID_WIRETOSURFACE_1 or RDPGFX_CMDID_WIRETOSURFACE_2 */
|
||||||
position = Stream_GetPosition(s);
|
position = Stream_GetPosition(s);
|
||||||
error = rdpgfx_server_packet_init_header(s,
|
error = rdpgfx_server_packet_init_header(s,
|
||||||
rdpgfx_surface_command_cmdid(cmd),
|
rdpgfx_surface_command_cmdid(cmd),
|
||||||
0); // Actual length will be filled later
|
0); // Actual length will be filled later
|
||||||
|
|
||||||
if (error != CHANNEL_RC_OK)
|
if (error != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
@ -761,7 +767,7 @@ static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
|
|||||||
{
|
{
|
||||||
position = Stream_GetPosition(s);
|
position = Stream_GetPosition(s);
|
||||||
error = rdpgfx_server_packet_init_header(s,
|
error = rdpgfx_server_packet_init_header(s,
|
||||||
RDPGFX_CMDID_ENDFRAME, 0);
|
RDPGFX_CMDID_ENDFRAME, 0);
|
||||||
|
|
||||||
if (error != CHANNEL_RC_OK)
|
if (error != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
@ -784,11 +790,12 @@ 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*
|
||||||
RDPGFX_DELETE_ENCODING_CONTEXT_PDU* pdu)
|
context,
|
||||||
|
RDPGFX_DELETE_ENCODING_CONTEXT_PDU* pdu)
|
||||||
{
|
{
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_DELETEENCODINGCONTEXT, 6);
|
RDPGFX_CMDID_DELETEENCODINGCONTEXT, 6);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -807,14 +814,14 @@ static UINT rdpgfx_send_delete_encoding_context_pdu(RdpgfxServerContext* context
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
UINT rdpgfx_send_solid_fill_pdu(RdpgfxServerContext* context,
|
UINT rdpgfx_send_solid_fill_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_SOLID_FILL_PDU* pdu)
|
RDPGFX_SOLID_FILL_PDU* pdu)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
UINT16 index;
|
UINT16 index;
|
||||||
RECTANGLE_16* fillRect;
|
RECTANGLE_16* fillRect;
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_SOLIDFILL,
|
RDPGFX_CMDID_SOLIDFILL,
|
||||||
8 + 8 * pdu->fillRectCount);
|
8 + 8 * pdu->fillRectCount);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -856,14 +863,14 @@ error:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_surface_to_surface_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_surface_to_surface_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_SURFACE_TO_SURFACE_PDU* pdu)
|
RDPGFX_SURFACE_TO_SURFACE_PDU* pdu)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
UINT16 index;
|
UINT16 index;
|
||||||
RDPGFX_POINT16* destPt;
|
RDPGFX_POINT16* destPt;
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_SURFACETOSURFACE,
|
RDPGFX_CMDID_SURFACETOSURFACE,
|
||||||
14 + 4 * pdu->destPtsCount);
|
14 + 4 * pdu->destPtsCount);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -906,11 +913,11 @@ error:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_surface_to_cache_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_surface_to_cache_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_SURFACE_TO_CACHE_PDU* pdu)
|
RDPGFX_SURFACE_TO_CACHE_PDU* pdu)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_SURFACETOCACHE, 20);
|
RDPGFX_CMDID_SURFACETOCACHE, 20);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -941,14 +948,14 @@ error:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_cache_to_surface_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_cache_to_surface_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_CACHE_TO_SURFACE_PDU* pdu)
|
RDPGFX_CACHE_TO_SURFACE_PDU* pdu)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
UINT16 index;
|
UINT16 index;
|
||||||
RDPGFX_POINT16* destPt;
|
RDPGFX_POINT16* destPt;
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_CACHETOSURFACE,
|
RDPGFX_CMDID_CACHETOSURFACE,
|
||||||
6 + 4 * pdu->destPtsCount);
|
6 + 4 * pdu->destPtsCount);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -983,10 +990,10 @@ error:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_map_surface_to_output_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_map_surface_to_output_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* pdu)
|
RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* pdu)
|
||||||
{
|
{
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_MAPSURFACETOOUTPUT, 12);
|
RDPGFX_CMDID_MAPSURFACETOOUTPUT, 12);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -1007,10 +1014,10 @@ static UINT rdpgfx_send_map_surface_to_output_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_map_surface_to_window_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_send_map_surface_to_window_pdu(RdpgfxServerContext* context,
|
||||||
RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* pdu)
|
RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* pdu)
|
||||||
{
|
{
|
||||||
wStream* s = rdpgfx_server_single_packet_new(
|
wStream* s = rdpgfx_server_single_packet_new(
|
||||||
RDPGFX_CMDID_MAPSURFACETOWINDOW, 18);
|
RDPGFX_CMDID_MAPSURFACETOWINDOW, 18);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
@ -1031,7 +1038,7 @@ static UINT rdpgfx_send_map_surface_to_window_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_recv_frame_acknowledge_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_recv_frame_acknowledge_pdu(RdpgfxServerContext* context,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
RDPGFX_FRAME_ACKNOWLEDGE_PDU pdu;
|
RDPGFX_FRAME_ACKNOWLEDGE_PDU pdu;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1053,7 +1060,7 @@ static UINT rdpgfx_recv_frame_acknowledge_pdu(RdpgfxServerContext* context,
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
WLog_ERR(TAG, "context->FrameAcknowledge failed with error %lu",
|
WLog_ERR(TAG, "context->FrameAcknowledge failed with error %lu",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
@ -1065,7 +1072,7 @@ static UINT rdpgfx_recv_frame_acknowledge_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
UINT16 index;
|
UINT16 index;
|
||||||
RDPGFX_CACHE_IMPORT_OFFER_PDU pdu;
|
RDPGFX_CACHE_IMPORT_OFFER_PDU pdu;
|
||||||
@ -1095,8 +1102,8 @@ static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pdu.cacheEntries = (RDPGFX_CACHE_ENTRY_METADATA*)
|
pdu.cacheEntries = (RDPGFX_CACHE_ENTRY_METADATA*)
|
||||||
calloc(pdu.cacheEntriesCount,
|
calloc(pdu.cacheEntriesCount,
|
||||||
sizeof(RDPGFX_CACHE_ENTRY_METADATA));
|
sizeof(RDPGFX_CACHE_ENTRY_METADATA));
|
||||||
|
|
||||||
if (!pdu.cacheEntries)
|
if (!pdu.cacheEntries)
|
||||||
{
|
{
|
||||||
@ -1118,7 +1125,7 @@ static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context,
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
WLog_ERR(TAG, "context->CacheImportOffer failed with error %lu",
|
WLog_ERR(TAG, "context->CacheImportOffer failed with error %lu",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pdu.cacheEntries);
|
free(pdu.cacheEntries);
|
||||||
@ -1131,7 +1138,7 @@ static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
UINT16 index;
|
UINT16 index;
|
||||||
RDPGFX_CAPSET* capsSet;
|
RDPGFX_CAPSET* capsSet;
|
||||||
@ -1172,7 +1179,7 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
|
|||||||
if (capsDataLength != 4)
|
if (capsDataLength != 4)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "capsDataLength does not equal to 4: %lu",
|
WLog_ERR(TAG, "capsDataLength does not equal to 4: %lu",
|
||||||
capsDataLength);
|
capsDataLength);
|
||||||
return ERROR_INVALID_DATA;
|
return ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1196,7 +1203,7 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context,
|
static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU pdu;
|
RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU pdu;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1218,7 +1225,7 @@ static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context,
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
WLog_ERR(TAG, "context->QoeFrameAcknowledge failed with error %lu",
|
WLog_ERR(TAG, "context->QoeFrameAcknowledge failed with error %lu",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
@ -1243,39 +1250,39 @@ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
WLog_DBG(TAG, "cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d",
|
WLog_DBG(TAG, "cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d",
|
||||||
rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId,
|
rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId,
|
||||||
header.flags, header.pduLength);
|
header.flags, header.pduLength);
|
||||||
|
|
||||||
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;
|
||||||
@ -1284,7 +1291,7 @@ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s)
|
|||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Error while parsing GFX cmdId: %s (0x%04X)",
|
WLog_ERR(TAG, "Error while parsing GFX cmdId: %s (0x%04X)",
|
||||||
rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId);
|
rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1293,7 +1300,7 @@ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s)
|
|||||||
if (end != (beg + header.pduLength))
|
if (end != (beg + header.pduLength))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Unexpected gfx pdu end: Actual: %d, Expected: %d",
|
WLog_ERR(TAG, "Unexpected gfx pdu end: Actual: %d, Expected: %d",
|
||||||
end, (beg + header.pduLength));
|
end, (beg + header.pduLength));
|
||||||
Stream_SetPosition(s, (beg + header.pduLength));
|
Stream_SetPosition(s, (beg + header.pduLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
||||||
@ -1337,14 +1343,14 @@ static void* rdpgfx_server_thread_func(void* arg)
|
|||||||
if ((error = rdpgfx_server_handle_messages(context)))
|
if ((error = rdpgfx_server_handle_messages(context)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdpgfx_server_handle_messages failed with error %lu",
|
WLog_ERR(TAG, "rdpgfx_server_handle_messages failed with error %lu",
|
||||||
error);
|
error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error && context->rdpcontext)
|
if (error && context->rdpcontext)
|
||||||
setChannelError(context->rdpcontext, error,
|
setChannelError(context->rdpcontext, error,
|
||||||
"rdpgfx_server_thread_func reported an error");
|
"rdpgfx_server_thread_func reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD)error);
|
ExitThread((DWORD)error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1362,18 +1368,18 @@ static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
|
|||||||
priv->SessionId = WTS_CURRENT_SESSION;
|
priv->SessionId = WTS_CURRENT_SESSION;
|
||||||
|
|
||||||
if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION,
|
if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION,
|
||||||
WTSSessionId, (LPSTR*) &pSessionId,
|
WTSSessionId, (LPSTR*) &pSessionId,
|
||||||
&BytesReturned) == FALSE)
|
&BytesReturned) == FALSE)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
|
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
|
||||||
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,
|
||||||
WTS_CHANNEL_OPTION_DYNAMIC);
|
WTS_CHANNEL_OPTION_DYNAMIC);
|
||||||
|
|
||||||
if (!priv->rdpgfx_channel)
|
if (!priv->rdpgfx_channel)
|
||||||
{
|
{
|
||||||
@ -1383,12 +1389,12 @@ static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
|
|||||||
|
|
||||||
/* Query for channel event handle */
|
/* Query for channel event handle */
|
||||||
if (!WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualEventHandle,
|
if (!WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualEventHandle,
|
||||||
&buffer, &BytesReturned)
|
&buffer, &BytesReturned)
|
||||||
|| (BytesReturned != sizeof(HANDLE)))
|
|| (BytesReturned != sizeof(HANDLE)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSVirtualChannelQuery failed "
|
WLog_ERR(TAG, "WTSVirtualChannelQuery failed "
|
||||||
"or invalid returned size(%d)",
|
"or invalid returned size(%d)",
|
||||||
BytesReturned);
|
BytesReturned);
|
||||||
|
|
||||||
if (buffer)
|
if (buffer)
|
||||||
WTSFreeMemory(buffer);
|
WTSFreeMemory(buffer);
|
||||||
@ -1414,9 +1420,9 @@ static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(priv->thread = CreateThread(NULL, 0,
|
if (!(priv->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE)
|
(LPTHREAD_START_ROUTINE)
|
||||||
rdpgfx_server_thread_func,
|
rdpgfx_server_thread_func,
|
||||||
(void*) context, 0, NULL)))
|
(void*) context, 0, NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
goto out_stopEvent;
|
goto out_stopEvent;
|
||||||
@ -1454,7 +1460,7 @@ static BOOL rdpgfx_server_close(RdpgfxServerContext* context)
|
|||||||
if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
|
if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu",
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1516,7 +1522,7 @@ RdpgfxServerContext* rdpgfx_server_context_new(HANDLE vcm)
|
|||||||
context->FrameAcknowledge = NULL;
|
context->FrameAcknowledge = NULL;
|
||||||
context->QoeFrameAcknowledge = NULL;
|
context->QoeFrameAcknowledge = NULL;
|
||||||
context->priv = priv = (RdpgfxServerPrivate*)
|
context->priv = priv = (RdpgfxServerPrivate*)
|
||||||
calloc(1, sizeof(RdpgfxServerPrivate));
|
calloc(1, sizeof(RdpgfxServerPrivate));
|
||||||
|
|
||||||
if (!priv)
|
if (!priv)
|
||||||
{
|
{
|
||||||
@ -1581,8 +1587,8 @@ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context)
|
|||||||
if (!priv->isReady)
|
if (!priv->isReady)
|
||||||
{
|
{
|
||||||
if (WTSVirtualChannelQuery(priv->rdpgfx_channel,
|
if (WTSVirtualChannelQuery(priv->rdpgfx_channel,
|
||||||
WTSVirtualChannelReady,
|
WTSVirtualChannelReady,
|
||||||
&buffer, &BytesReturned) == FALSE)
|
&buffer, &BytesReturned) == FALSE)
|
||||||
{
|
{
|
||||||
if (GetLastError() == ERROR_NO_DATA)
|
if (GetLastError() == ERROR_NO_DATA)
|
||||||
return ERROR_NO_DATA;
|
return ERROR_NO_DATA;
|
||||||
@ -1601,7 +1607,7 @@ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context)
|
|||||||
Stream_SetPosition(s, 0);
|
Stream_SetPosition(s, 0);
|
||||||
|
|
||||||
if (!WTSVirtualChannelRead(priv->rdpgfx_channel,
|
if (!WTSVirtualChannelRead(priv->rdpgfx_channel,
|
||||||
0, NULL, 0, &BytesReturned))
|
0, NULL, 0, &BytesReturned))
|
||||||
{
|
{
|
||||||
if (GetLastError() == ERROR_NO_DATA)
|
if (GetLastError() == ERROR_NO_DATA)
|
||||||
return ERROR_NO_DATA;
|
return ERROR_NO_DATA;
|
||||||
@ -1620,8 +1626,8 @@ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (WTSVirtualChannelRead(priv->rdpgfx_channel, 0,
|
if (WTSVirtualChannelRead(priv->rdpgfx_channel, 0,
|
||||||
(PCHAR) Stream_Buffer(s),
|
(PCHAR) Stream_Buffer(s),
|
||||||
Stream_Capacity(s), &BytesReturned) == FALSE)
|
Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
@ -1635,7 +1641,7 @@ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context)
|
|||||||
if ((ret = rdpgfx_server_receive_pdu(context, s)))
|
if ((ret = rdpgfx_server_receive_pdu(context, s)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdpgfx_server_receive_pdu "
|
WLog_ERR(TAG, "rdpgfx_server_receive_pdu "
|
||||||
"failed with error %lu!", ret);
|
"failed with error %lu!", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -182,7 +181,7 @@ static void* rdpsnd_schedule_thread(void* arg)
|
|||||||
|
|
||||||
if (error && rdpsnd->rdpcontext)
|
if (error && rdpsnd->rdpcontext)
|
||||||
setChannelError(rdpsnd->rdpcontext, error,
|
setChannelError(rdpsnd->rdpcontext, error,
|
||||||
"rdpsnd_schedule_thread reported an error");
|
"rdpsnd_schedule_thread reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD)error);
|
ExitThread((DWORD)error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -226,7 +225,7 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
rdpsnd->ClientFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) *
|
rdpsnd->ClientFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) *
|
||||||
rdpsnd->NumberOfServerFormats);
|
rdpsnd->NumberOfServerFormats);
|
||||||
|
|
||||||
for (index = 0; index < (int) rdpsnd->NumberOfServerFormats; index++)
|
for (index = 0; index < (int) rdpsnd->NumberOfServerFormats; index++)
|
||||||
{
|
{
|
||||||
@ -263,11 +262,11 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
|
|||||||
#if 0
|
#if 0
|
||||||
WLog_ERR(TAG, "Server ");
|
WLog_ERR(TAG, "Server ");
|
||||||
rdpsnd_print_audio_formats(rdpsnd->ServerFormats,
|
rdpsnd_print_audio_formats(rdpsnd->ServerFormats,
|
||||||
rdpsnd->NumberOfServerFormats);
|
rdpsnd->NumberOfServerFormats);
|
||||||
WLog_ERR(TAG, "");
|
WLog_ERR(TAG, "");
|
||||||
WLog_ERR(TAG, "Client ");
|
WLog_ERR(TAG, "Client ");
|
||||||
rdpsnd_print_audio_formats(rdpsnd->ClientFormats,
|
rdpsnd_print_audio_formats(rdpsnd->ClientFormats,
|
||||||
rdpsnd->NumberOfClientFormats);
|
rdpsnd->NumberOfClientFormats);
|
||||||
WLog_ERR(TAG, "");
|
WLog_ERR(TAG, "");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -348,7 +347,7 @@ static UINT rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd,
|
static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd,
|
||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
UINT16 wVersion;
|
UINT16 wVersion;
|
||||||
@ -377,7 +376,7 @@ static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd,
|
|||||||
return ERROR_BAD_LENGTH;
|
return ERROR_BAD_LENGTH;
|
||||||
|
|
||||||
rdpsnd->ServerFormats = (AUDIO_FORMAT*) calloc(wNumberOfFormats,
|
rdpsnd->ServerFormats = (AUDIO_FORMAT*) calloc(wNumberOfFormats,
|
||||||
sizeof(AUDIO_FORMAT));
|
sizeof(AUDIO_FORMAT));
|
||||||
|
|
||||||
if (!rdpsnd->ServerFormats)
|
if (!rdpsnd->ServerFormats)
|
||||||
return CHANNEL_RC_NO_MEMORY;
|
return CHANNEL_RC_NO_MEMORY;
|
||||||
@ -441,7 +440,7 @@ out_fail:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd,
|
static UINT rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd,
|
||||||
UINT16 wTimeStamp, UINT16 wPackSize)
|
UINT16 wTimeStamp, UINT16 wPackSize)
|
||||||
{
|
{
|
||||||
wStream* pdu;
|
wStream* pdu;
|
||||||
pdu = Stream_New(NULL, 8);
|
pdu = Stream_New(NULL, 8);
|
||||||
@ -458,8 +457,8 @@ static UINT rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd,
|
|||||||
Stream_Write_UINT16(pdu, wTimeStamp);
|
Stream_Write_UINT16(pdu, wTimeStamp);
|
||||||
Stream_Write_UINT16(pdu, wPackSize);
|
Stream_Write_UINT16(pdu, wPackSize);
|
||||||
WLog_Print(rdpsnd->log, WLOG_DEBUG,
|
WLog_Print(rdpsnd->log, WLOG_DEBUG,
|
||||||
"Training Response: wTimeStamp: %d wPackSize: %d",
|
"Training Response: wTimeStamp: %d wPackSize: %d",
|
||||||
wTimeStamp, wPackSize);
|
wTimeStamp, wPackSize);
|
||||||
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,8 +478,8 @@ static UINT rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
Stream_Read_UINT16(s, wTimeStamp);
|
Stream_Read_UINT16(s, wTimeStamp);
|
||||||
Stream_Read_UINT16(s, wPackSize);
|
Stream_Read_UINT16(s, wPackSize);
|
||||||
WLog_Print(rdpsnd->log, WLOG_DEBUG,
|
WLog_Print(rdpsnd->log, WLOG_DEBUG,
|
||||||
"Training Request: wTimeStamp: %d wPackSize: %d",
|
"Training Request: wTimeStamp: %d wPackSize: %d",
|
||||||
wTimeStamp, wPackSize);
|
wTimeStamp, wPackSize);
|
||||||
return rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
|
return rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +489,7 @@ static UINT rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s,
|
static UINT rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s,
|
||||||
UINT16 BodySize)
|
UINT16 BodySize)
|
||||||
{
|
{
|
||||||
UINT16 wFormatNo;
|
UINT16 wFormatNo;
|
||||||
AUDIO_FORMAT* format;
|
AUDIO_FORMAT* format;
|
||||||
@ -507,7 +506,7 @@ static UINT rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s,
|
|||||||
rdpsnd->waveDataSize = BodySize - 8;
|
rdpsnd->waveDataSize = BodySize - 8;
|
||||||
format = &rdpsnd->ClientFormats[wFormatNo];
|
format = &rdpsnd->ClientFormats[wFormatNo];
|
||||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveInfo: cBlockNo: %d wFormatNo: %d",
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveInfo: cBlockNo: %d wFormatNo: %d",
|
||||||
rdpsnd->cBlockNo, wFormatNo);
|
rdpsnd->cBlockNo, wFormatNo);
|
||||||
|
|
||||||
if (!rdpsnd->isOpen)
|
if (!rdpsnd->isOpen)
|
||||||
{
|
{
|
||||||
@ -543,7 +542,7 @@ static UINT rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd,
|
static UINT rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd,
|
||||||
UINT16 wTimeStamp, BYTE cConfirmedBlockNo)
|
UINT16 wTimeStamp, BYTE cConfirmedBlockNo)
|
||||||
{
|
{
|
||||||
wStream* pdu;
|
wStream* pdu;
|
||||||
pdu = Stream_New(NULL, 8);
|
pdu = Stream_New(NULL, 8);
|
||||||
@ -571,8 +570,8 @@ static UINT rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd,
|
|||||||
static UINT rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave)
|
static UINT rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave)
|
||||||
{
|
{
|
||||||
WLog_Print(rdpsnd->log, WLOG_DEBUG,
|
WLog_Print(rdpsnd->log, WLOG_DEBUG,
|
||||||
"WaveConfirm: cBlockNo: %d wTimeStamp: %d wTimeDiff: %d",
|
"WaveConfirm: cBlockNo: %d wTimeStamp: %d wTimeDiff: %d",
|
||||||
wave->cBlockNo, wave->wTimeStampB, wave->wTimeStampB - wave->wTimeStampA);
|
wave->cBlockNo, wave->wTimeStampB, wave->wTimeStampB - wave->wTimeStampA);
|
||||||
return rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
|
return rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,13 +581,13 @@ static UINT rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device,
|
static UINT rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device,
|
||||||
RDPSND_WAVE* wave)
|
RDPSND_WAVE* wave)
|
||||||
{
|
{
|
||||||
if (device->DisableConfirmThread)
|
if (device->DisableConfirmThread)
|
||||||
return rdpsnd_confirm_wave(device->rdpsnd, wave);
|
return rdpsnd_confirm_wave(device->rdpsnd, wave);
|
||||||
|
|
||||||
if (!MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave,
|
if (!MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave,
|
||||||
NULL))
|
NULL))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "MessageQueue_Post failed!");
|
WLog_ERR(TAG, "MessageQueue_Post failed!");
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
@ -637,7 +636,7 @@ static UINT rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
format = &rdpsnd->ClientFormats[rdpsnd->wCurrentFormatNo];
|
format = &rdpsnd->ClientFormats[rdpsnd->wCurrentFormatNo];
|
||||||
wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size);
|
wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size);
|
||||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Wave: cBlockNo: %d wTimeStamp: %d",
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Wave: cBlockNo: %d wTimeStamp: %d",
|
||||||
wave->cBlockNo, wave->wTimeStampA);
|
wave->cBlockNo, wave->wTimeStampA);
|
||||||
|
|
||||||
if (!rdpsnd->device)
|
if (!rdpsnd->device)
|
||||||
{
|
{
|
||||||
@ -777,7 +776,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd,
|
static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd,
|
||||||
rdpsndDevicePlugin* device)
|
rdpsndDevicePlugin* device)
|
||||||
{
|
{
|
||||||
if (rdpsnd->device)
|
if (rdpsnd->device)
|
||||||
{
|
{
|
||||||
@ -796,14 +795,14 @@ static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd,
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name,
|
static UINT rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name,
|
||||||
ADDIN_ARGV* args)
|
ADDIN_ARGV* args)
|
||||||
{
|
{
|
||||||
PFREERDP_RDPSND_DEVICE_ENTRY entry;
|
PFREERDP_RDPSND_DEVICE_ENTRY entry;
|
||||||
FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;
|
FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;
|
||||||
\
|
\
|
||||||
UINT error;
|
UINT error;
|
||||||
entry = (PFREERDP_RDPSND_DEVICE_ENTRY)
|
entry = (PFREERDP_RDPSND_DEVICE_ENTRY)
|
||||||
freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0);
|
freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0);
|
||||||
|
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
@ -861,7 +860,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
|
|||||||
{
|
{
|
||||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||||
rdpsnd_args, flags, rdpsnd, NULL, NULL);
|
rdpsnd_args, flags, rdpsnd, NULL, NULL);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||||
@ -958,7 +957,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
if ((status = rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args)))
|
if ((status = rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
||||||
rdpsnd->subsystem, status);
|
rdpsnd->subsystem, status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -973,7 +972,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
|
|
||||||
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
||||||
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
||||||
subsystem_name, status);
|
subsystem_name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -986,7 +985,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
|
|
||||||
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
||||||
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
||||||
subsystem_name, status);
|
subsystem_name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -999,7 +998,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
|
|
||||||
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
||||||
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
||||||
subsystem_name, status);
|
subsystem_name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1012,7 +1011,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
|
|
||||||
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
||||||
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
||||||
subsystem_name, status);
|
subsystem_name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1025,7 +1024,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
|
|
||||||
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
||||||
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
||||||
subsystem_name, status);
|
subsystem_name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1038,7 +1037,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
|
|
||||||
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
||||||
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
||||||
subsystem_name, status);
|
subsystem_name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1051,7 +1050,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
|
|
||||||
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
|
||||||
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
|
||||||
subsystem_name, status);
|
subsystem_name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1084,8 +1083,8 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
|
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
|
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
|
||||||
(void*) rdpsnd, 0, NULL);
|
(void*) rdpsnd, 0, NULL);
|
||||||
|
|
||||||
if (!rdpsnd->ScheduleThread)
|
if (!rdpsnd->ScheduleThread)
|
||||||
{
|
{
|
||||||
@ -1130,14 +1129,14 @@ UINT rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = rdpsnd->channelEntryPoints.pVirtualChannelWrite(rdpsnd->OpenHandle,
|
status = rdpsnd->channelEntryPoints.pVirtualChannelWrite(rdpsnd->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -1149,7 +1148,7 @@ UINT rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
|
static UINT rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
|
||||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
|
|
||||||
@ -1205,8 +1204,8 @@ static UINT rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle,
|
static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle,
|
||||||
UINT event,
|
UINT event,
|
||||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
rdpsndPlugin* rdpsnd = s_TLSPluginContext;
|
rdpsndPlugin* rdpsnd = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1221,9 +1220,9 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||||
if ((error = rdpsnd_virtual_channel_event_data_received(rdpsnd, pData,
|
if ((error = rdpsnd_virtual_channel_event_data_received(rdpsnd, pData,
|
||||||
dataLength, totalLength, dataFlags)))
|
dataLength, totalLength, dataFlags)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"rdpsnd_virtual_channel_event_data_received failed with error %lu", error);
|
"rdpsnd_virtual_channel_event_data_received failed with error %lu", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1237,7 +1236,7 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle,
|
|||||||
|
|
||||||
if (error && rdpsnd->rdpcontext)
|
if (error && rdpsnd->rdpcontext)
|
||||||
setChannelError(rdpsnd->rdpcontext, error,
|
setChannelError(rdpsnd->rdpcontext, error,
|
||||||
"rdpsnd_virtual_channel_open_event reported an error");
|
"rdpsnd_virtual_channel_open_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* rdpsnd_virtual_channel_client_thread(void* arg)
|
static void* rdpsnd_virtual_channel_client_thread(void* arg)
|
||||||
@ -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");
|
||||||
@ -1289,7 +1288,7 @@ out:
|
|||||||
|
|
||||||
if (error && rdpsnd->rdpcontext)
|
if (error && rdpsnd->rdpcontext)
|
||||||
setChannelError(rdpsnd->rdpcontext, error,
|
setChannelError(rdpsnd->rdpcontext, error,
|
||||||
"rdpsnd_virtual_channel_client_thread reported an error");
|
"rdpsnd_virtual_channel_client_thread reported an error");
|
||||||
|
|
||||||
rdpsnd_process_disconnect(rdpsnd);
|
rdpsnd_process_disconnect(rdpsnd);
|
||||||
ExitThread((DWORD)error);
|
ExitThread((DWORD)error);
|
||||||
@ -1302,17 +1301,17 @@ out:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin,
|
static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin,
|
||||||
LPVOID pData, UINT32 dataLength)
|
LPVOID pData, UINT32 dataLength)
|
||||||
{
|
{
|
||||||
UINT32 status;
|
UINT32 status;
|
||||||
status = plugin->channelEntryPoints.pVirtualChannelOpen(plugin->InitHandle,
|
status = plugin->channelEntryPoints.pVirtualChannelOpen(plugin->InitHandle,
|
||||||
&plugin->OpenHandle, plugin->channelDef.name,
|
&plugin->OpenHandle, plugin->channelDef.name,
|
||||||
rdpsnd_virtual_channel_open_event);
|
rdpsnd_virtual_channel_open_event);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1325,8 +1324,8 @@ static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugin->thread = CreateThread(NULL, 0,
|
plugin->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin,
|
(LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
|
|
||||||
if (!plugin->thread)
|
if (!plugin->thread)
|
||||||
{
|
{
|
||||||
@ -1363,7 +1362,7 @@ static UINT rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd)
|
|||||||
if (CHANNEL_RC_OK != error)
|
if (CHANNEL_RC_OK != error)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||||
WTSErrorToString(error), error);
|
WTSErrorToString(error), error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1412,7 +1411,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle,
|
static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle,
|
||||||
UINT event, LPVOID pData, UINT dataLength)
|
UINT event, LPVOID pData, UINT dataLength)
|
||||||
{
|
{
|
||||||
rdpsndPlugin* plugin = s_TLSPluginContext;
|
rdpsndPlugin* plugin = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1428,14 +1427,14 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
case CHANNEL_EVENT_CONNECTED:
|
case CHANNEL_EVENT_CONNECTED:
|
||||||
if ((error = rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength)))
|
if ((error = rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength)))
|
||||||
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_connected failed with error %lu!",
|
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_connected failed with error %lu!",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_DISCONNECTED:
|
case CHANNEL_EVENT_DISCONNECTED:
|
||||||
if ((error = rdpsnd_virtual_channel_event_disconnected(plugin)))
|
if ((error = rdpsnd_virtual_channel_event_disconnected(plugin)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"rdpsnd_virtual_channel_event_disconnected failed with error %lu!", error);
|
"rdpsnd_virtual_channel_event_disconnected failed with error %lu!", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1449,7 +1448,7 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
|
|
||||||
if (error && plugin->rdpcontext)
|
if (error && plugin->rdpcontext)
|
||||||
setChannelError(plugin->rdpcontext, error,
|
setChannelError(plugin->rdpcontext, error,
|
||||||
"rdpsnd_virtual_channel_init_event reported an error");
|
"rdpsnd_virtual_channel_init_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rdpsnd is always built-in */
|
/* rdpsnd is always built-in */
|
||||||
@ -1495,16 +1494,16 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints,
|
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints,
|
||||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||||
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
|
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
|
||||||
rc = rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
|
rc = rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
|
||||||
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||||
rdpsnd_virtual_channel_init_event);
|
rdpsnd_virtual_channel_init_event);
|
||||||
|
|
||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
free(rdpsnd);
|
free(rdpsnd);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -261,22 +261,21 @@ static void* rdpsnd_server_thread(void* arg)
|
|||||||
{
|
{
|
||||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
if (status == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
|
||||||
{
|
|
||||||
error = GetLastError();
|
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (status == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
error = GetLastError();
|
||||||
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||||
|
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,50 +418,51 @@ 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;
|
||||||
|
|
||||||
if ((format->nSamplesPerSec == context->src_format.nSamplesPerSec) &&
|
if ((format->nSamplesPerSec == context->src_format.nSamplesPerSec) &&
|
||||||
(format->nChannels == context->src_format.nChannels))
|
(format->nChannels == context->src_format.nChannels))
|
||||||
{
|
{
|
||||||
src = context->priv->out_buffer;
|
src = context->priv->out_buffer;
|
||||||
frames = context->priv->out_pending_frames;
|
frames = context->priv->out_pending_frames;
|
||||||
}
|
}
|
||||||
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->src_bytes_per_sample, context->src_format.nChannels,
|
context->priv->out_buffer,
|
||||||
context->src_format.nSamplesPerSec, context->priv->out_pending_frames,
|
context->priv->src_bytes_per_sample, context->src_format.nChannels,
|
||||||
format->nChannels, format->nSamplesPerSec);
|
context->src_format.nSamplesPerSec, context->priv->out_pending_frames,
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
context->priv->dsp_context->encode_ima_adpcm(context->priv->dsp_context,
|
context->priv->dsp_context->encode_ima_adpcm(context->priv->dsp_context,
|
||||||
src, size, format->nChannels, format->nBlockAlign);
|
src, size, format->nChannels, format->nBlockAlign);
|
||||||
src = context->priv->dsp_context->adpcm_buffer;
|
src = context->priv->dsp_context->adpcm_buffer;
|
||||||
size = context->priv->dsp_context->adpcm_size;
|
size = context->priv->dsp_context->adpcm_size;
|
||||||
}
|
}
|
||||||
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
|
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
|
||||||
{
|
{
|
||||||
context->priv->dsp_context->encode_ms_adpcm(context->priv->dsp_context,
|
context->priv->dsp_context->encode_ms_adpcm(context->priv->dsp_context,
|
||||||
src, size, format->nChannels, format->nBlockAlign);
|
src, size, format->nChannels, format->nBlockAlign);
|
||||||
src = context->priv->dsp_context->adpcm_buffer;
|
src = context->priv->dsp_context->adpcm_buffer;
|
||||||
size = context->priv->dsp_context->adpcm_size;
|
size = context->priv->dsp_context->adpcm_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
bytesReturned);
|
"error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)",
|
||||||
|
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!");
|
||||||
@ -682,17 +700,16 @@ 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;
|
||||||
@ -714,7 +731,8 @@ 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)
|
||||||
@ -722,11 +740,12 @@ static UINT rdpsnd_server_stop(RdpsndServerContext* context)
|
|||||||
SetEvent(context->priv->StopEvent);
|
SetEvent(context->priv->StopEvent);
|
||||||
|
|
||||||
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
|
if (WaitForSingleObject(context->priv->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(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;
|
||||||
}
|
}
|
||||||
|
@ -59,11 +59,11 @@ static UINT remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = remdesk->channelEntryPoints.pVirtualChannelWrite(remdesk->OpenHandle,
|
status = remdesk->channelEntryPoints.pVirtualChannelWrite(remdesk->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
|
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ static UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
|
|||||||
name = "Expert";
|
name = "Expert";
|
||||||
|
|
||||||
remdesk->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(password,
|
remdesk->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(password,
|
||||||
settings->RemoteAssistancePassStub, &(remdesk->EncryptedPassStubSize));
|
settings->RemoteAssistancePassStub, &(remdesk->EncryptedPassStubSize));
|
||||||
|
|
||||||
if (!remdesk->EncryptedPassStub)
|
if (!remdesk->EncryptedPassStub)
|
||||||
{
|
{
|
||||||
@ -109,7 +109,7 @@ static UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pass = freerdp_assistance_bin_to_hex_string(remdesk->EncryptedPassStub,
|
pass = freerdp_assistance_bin_to_hex_string(remdesk->EncryptedPassStub,
|
||||||
remdesk->EncryptedPassStubSize);
|
remdesk->EncryptedPassStubSize);
|
||||||
|
|
||||||
if (!pass)
|
if (!pass)
|
||||||
{
|
{
|
||||||
@ -134,7 +134,7 @@ static UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
|
|||||||
* @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,
|
static UINT remdesk_read_channel_header(wStream* s,
|
||||||
REMDESK_CHANNEL_HEADER* header)
|
REMDESK_CHANNEL_HEADER* header)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
UINT32 ChannelNameLen;
|
UINT32 ChannelNameLen;
|
||||||
@ -170,7 +170,7 @@ static UINT remdesk_read_channel_header(wStream* s,
|
|||||||
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)
|
||||||
@ -188,7 +188,7 @@ static UINT remdesk_read_channel_header(wStream* s,
|
|||||||
* @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,
|
static UINT remdesk_write_channel_header(wStream* s,
|
||||||
REMDESK_CHANNEL_HEADER* header)
|
REMDESK_CHANNEL_HEADER* header)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
UINT32 ChannelNameLen;
|
UINT32 ChannelNameLen;
|
||||||
@ -225,7 +225,7 @@ 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,
|
static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader,
|
||||||
UINT32 msgType, UINT32 msgSize)
|
UINT32 msgType, UINT32 msgSize)
|
||||||
{
|
{
|
||||||
ctlHeader->msgType = msgType;
|
ctlHeader->msgType = msgType;
|
||||||
strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME);
|
strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME);
|
||||||
@ -239,7 +239,7 @@ static UINT remdesk_prepare_ctl_header(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_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk,
|
static UINT remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk,
|
||||||
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||||
{
|
{
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ static UINT remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk,
|
|||||||
* @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(remdeskPlugin* remdesk,
|
static UINT remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk,
|
||||||
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||||
{
|
{
|
||||||
UINT32 versionMajor;
|
UINT32 versionMajor;
|
||||||
UINT32 versionMinor;
|
UINT32 versionMinor;
|
||||||
@ -308,7 +308,7 @@ static UINT remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s,
|
static UINT remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s,
|
||||||
REMDESK_CHANNEL_HEADER* header, UINT32* pResult)
|
REMDESK_CHANNEL_HEADER* header, UINT32* pResult)
|
||||||
{
|
{
|
||||||
UINT32 result;
|
UINT32 result;
|
||||||
|
|
||||||
@ -349,7 +349,7 @@ static UINT remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk)
|
|||||||
pdu.expertBlob = remdesk->ExpertBlob;
|
pdu.expertBlob = remdesk->ExpertBlob;
|
||||||
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
|
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
|
||||||
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1,
|
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1,
|
||||||
&raConnectionStringW, 0);
|
&raConnectionStringW, 0);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -369,7 +369,7 @@ static UINT remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk)
|
|||||||
|
|
||||||
cbExpertBlobW = status * 2;
|
cbExpertBlobW = status * 2;
|
||||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_AUTHENTICATE,
|
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_AUTHENTICATE,
|
||||||
cbRaConnectionStringW + cbExpertBlobW);
|
cbRaConnectionStringW + cbExpertBlobW);
|
||||||
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)
|
||||||
@ -412,7 +412,7 @@ static UINT remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk)
|
|||||||
REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu;
|
REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu;
|
||||||
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
|
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
|
||||||
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1,
|
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1,
|
||||||
&raConnectionStringW, 0);
|
&raConnectionStringW, 0);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -422,7 +422,7 @@ static UINT remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk)
|
|||||||
|
|
||||||
cbRaConnectionStringW = status * 2;
|
cbRaConnectionStringW = status * 2;
|
||||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_REMOTE_CONTROL_DESKTOP,
|
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_REMOTE_CONTROL_DESKTOP,
|
||||||
cbRaConnectionStringW);
|
cbRaConnectionStringW);
|
||||||
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)
|
||||||
@ -479,7 +479,7 @@ static UINT remdesk_send_ctl_verify_password_pdu(remdeskPlugin* remdesk)
|
|||||||
|
|
||||||
cbExpertBlobW = status * 2;
|
cbExpertBlobW = status * 2;
|
||||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERIFY_PASSWORD,
|
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERIFY_PASSWORD,
|
||||||
cbExpertBlobW);
|
cbExpertBlobW);
|
||||||
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)
|
||||||
@ -525,7 +525,7 @@ static UINT remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk)
|
|||||||
pdu.EncryptedPasswordLength = remdesk->EncryptedPassStubSize;
|
pdu.EncryptedPasswordLength = remdesk->EncryptedPassStubSize;
|
||||||
pdu.EncryptedPassword = remdesk->EncryptedPassStub;
|
pdu.EncryptedPassword = remdesk->EncryptedPassStub;
|
||||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_EXPERT_ON_VISTA,
|
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_EXPERT_ON_VISTA,
|
||||||
pdu.EncryptedPasswordLength);
|
pdu.EncryptedPasswordLength);
|
||||||
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)
|
||||||
@ -546,7 +546,7 @@ static UINT remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s,
|
static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s,
|
||||||
REMDESK_CHANNEL_HEADER* header)
|
REMDESK_CHANNEL_HEADER* header)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
UINT32 msgType = 0;
|
UINT32 msgType = 0;
|
||||||
@ -579,7 +579,7 @@ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s,
|
|||||||
case REMDESK_CTL_SERVER_ANNOUNCE:
|
case REMDESK_CTL_SERVER_ANNOUNCE:
|
||||||
if ((error = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header)))
|
if ((error = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header)))
|
||||||
WLog_ERR(TAG, "remdesk_recv_ctl_server_announce_pdu failed with error %lu",
|
WLog_ERR(TAG, "remdesk_recv_ctl_server_announce_pdu failed with error %lu",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -610,7 +610,7 @@ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s,
|
|||||||
if ((error = remdesk_send_ctl_remote_control_desktop_pdu(remdesk)))
|
if ((error = remdesk_send_ctl_remote_control_desktop_pdu(remdesk)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"remdesk_send_ctl_remote_control_desktop_pdu failed with error %lu", error);
|
"remdesk_send_ctl_remote_control_desktop_pdu failed with error %lu", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -619,14 +619,14 @@ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s,
|
|||||||
if ((error = remdesk_send_ctl_expert_on_vista_pdu(remdesk)))
|
if ((error = remdesk_send_ctl_expert_on_vista_pdu(remdesk)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "remdesk_send_ctl_expert_on_vista_pdu failed with error %lu",
|
WLog_ERR(TAG, "remdesk_send_ctl_expert_on_vista_pdu failed with error %lu",
|
||||||
error);
|
error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = remdesk_send_ctl_verify_password_pdu(remdesk)))
|
if ((error = remdesk_send_ctl_verify_password_pdu(remdesk)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %lu",
|
WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %lu",
|
||||||
error);
|
error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -728,14 +728,14 @@ static UINT remdesk_send(remdeskPlugin* remdesk, wStream* s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
|
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
|
||||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -747,7 +747,7 @@ static UINT remdesk_send(remdeskPlugin* remdesk, wStream* s)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
|
static UINT remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
|
||||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
wStream* data_in;
|
wStream* data_in;
|
||||||
|
|
||||||
@ -803,8 +803,8 @@ static UINT remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle,
|
static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle,
|
||||||
UINT event,
|
UINT event,
|
||||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||||
{
|
{
|
||||||
remdeskPlugin* remdesk = s_TLSPluginContext;
|
remdeskPlugin* remdesk = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -819,9 +819,9 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||||
if ((error = remdesk_virtual_channel_event_data_received(remdesk, pData,
|
if ((error = remdesk_virtual_channel_event_data_received(remdesk, pData,
|
||||||
dataLength, totalLength, dataFlags)))
|
dataLength, totalLength, dataFlags)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"remdesk_virtual_channel_event_data_received failed with error %lu!", error);
|
"remdesk_virtual_channel_event_data_received failed with error %lu!", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -839,7 +839,7 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle,
|
|||||||
|
|
||||||
if (error && remdesk->rdpcontext)
|
if (error && remdesk->rdpcontext)
|
||||||
setChannelError(remdesk->rdpcontext, error,
|
setChannelError(remdesk->rdpcontext, error,
|
||||||
"remdesk_virtual_channel_open_event reported an error");
|
"remdesk_virtual_channel_open_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* remdesk_virtual_channel_client_thread(void* arg)
|
static void* remdesk_virtual_channel_client_thread(void* arg)
|
||||||
@ -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);
|
||||||
|
|
||||||
@ -885,7 +884,7 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
|
|||||||
|
|
||||||
if (error && remdesk->rdpcontext)
|
if (error && remdesk->rdpcontext)
|
||||||
setChannelError(remdesk->rdpcontext, error,
|
setChannelError(remdesk->rdpcontext, error,
|
||||||
"remdesk_virtual_channel_client_thread reported an error");
|
"remdesk_virtual_channel_client_thread reported an error");
|
||||||
|
|
||||||
ExitThread((DWORD)error);
|
ExitThread((DWORD)error);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -897,18 +896,18 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk,
|
static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk,
|
||||||
LPVOID pData, UINT32 dataLength)
|
LPVOID pData, UINT32 dataLength)
|
||||||
{
|
{
|
||||||
UINT32 status;
|
UINT32 status;
|
||||||
UINT error;
|
UINT error;
|
||||||
status = remdesk->channelEntryPoints.pVirtualChannelOpen(remdesk->InitHandle,
|
status = remdesk->channelEntryPoints.pVirtualChannelOpen(remdesk->InitHandle,
|
||||||
&remdesk->OpenHandle, remdesk->channelDef.name,
|
&remdesk->OpenHandle, remdesk->channelDef.name,
|
||||||
remdesk_virtual_channel_open_event);
|
remdesk_virtual_channel_open_event);
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,8 +921,8 @@ static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
remdesk->thread = CreateThread(NULL, 0,
|
remdesk->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk,
|
(LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
|
|
||||||
if (!remdesk->thread)
|
if (!remdesk->thread)
|
||||||
{
|
{
|
||||||
@ -965,7 +964,7 @@ static UINT remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk)
|
|||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
remdesk->OpenHandle = 0;
|
remdesk->OpenHandle = 0;
|
||||||
@ -986,8 +985,8 @@ static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle,
|
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle,
|
||||||
UINT event, LPVOID pData,
|
UINT event, LPVOID pData,
|
||||||
UINT dataLength)
|
UINT dataLength)
|
||||||
{
|
{
|
||||||
remdeskPlugin* remdesk = s_TLSPluginContext;
|
remdeskPlugin* remdesk = s_TLSPluginContext;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
@ -1002,16 +1001,16 @@ static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
{
|
{
|
||||||
case CHANNEL_EVENT_CONNECTED:
|
case CHANNEL_EVENT_CONNECTED:
|
||||||
if ((error = remdesk_virtual_channel_event_connected(remdesk, pData,
|
if ((error = remdesk_virtual_channel_event_connected(remdesk, pData,
|
||||||
dataLength)))
|
dataLength)))
|
||||||
WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu",
|
WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu",
|
||||||
error);
|
error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_EVENT_DISCONNECTED:
|
case CHANNEL_EVENT_DISCONNECTED:
|
||||||
if ((error = remdesk_virtual_channel_event_disconnected(remdesk)))
|
if ((error = remdesk_virtual_channel_event_disconnected(remdesk)))
|
||||||
WLog_ERR(TAG,
|
WLog_ERR(TAG,
|
||||||
"remdesk_virtual_channel_event_disconnected failed with error %lu", error);
|
"remdesk_virtual_channel_event_disconnected failed with error %lu", error);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1022,7 +1021,7 @@ static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle,
|
|||||||
|
|
||||||
if (error && remdesk->rdpcontext)
|
if (error && remdesk->rdpcontext)
|
||||||
setChannelError(remdesk->rdpcontext, error,
|
setChannelError(remdesk->rdpcontext, error,
|
||||||
"remdesk_virtual_channel_init_event reported an error");
|
"remdesk_virtual_channel_init_event reported an error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remdesk is always built-in */
|
/* remdesk is always built-in */
|
||||||
@ -1075,27 +1074,29 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints,
|
CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints,
|
||||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||||
rc = remdesk->channelEntryPoints.pVirtualChannelInit(&remdesk->InitHandle,
|
rc = remdesk->channelEntryPoints.pVirtualChannelInit(&remdesk->InitHandle,
|
||||||
&remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
&remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||||
remdesk_virtual_channel_init_event);
|
remdesk_virtual_channel_init_event);
|
||||||
|
|
||||||
if (CHANNEL_RC_OK != rc)
|
if (CHANNEL_RC_OK != rc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(rc), rc);
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
remdesk->channelEntryPoints.pInterface = *
|
remdesk->channelEntryPoints.pInterface = *
|
||||||
(remdesk->channelEntryPoints.ppInterface);
|
(remdesk->channelEntryPoints.ppInterface);
|
||||||
remdesk->channelEntryPoints.ppInterface = &
|
remdesk->channelEntryPoints.ppInterface = &
|
||||||
(remdesk->channelEntryPoints.pInterface);
|
(remdesk->channelEntryPoints.pInterface);
|
||||||
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;
|
||||||
|
@ -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,11 +302,9 @@ 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);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -317,7 +313,7 @@ static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* co
|
|||||||
}
|
}
|
||||||
|
|
||||||
WLog_INFO(TAG, "RaConnectionString: %s",
|
WLog_INFO(TAG, "RaConnectionString: %s",
|
||||||
pdu.raConnectionString);
|
pdu.raConnectionString);
|
||||||
free(pdu.raConnectionString);
|
free(pdu.raConnectionString);
|
||||||
|
|
||||||
if ((error = remdesk_send_ctl_result_pdu(context, 0)))
|
if ((error = remdesk_send_ctl_result_pdu(context, 0)))
|
||||||
@ -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,11 +370,9 @@ 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);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -389,9 +381,8 @@ 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);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -401,10 +392,9 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
WLog_INFO(TAG, "RaConnectionString: %s ExpertBlob: %s",
|
WLog_INFO(TAG, "RaConnectionString: %s ExpertBlob: %s",
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,22 +635,21 @@ static void* remdesk_server_thread(void* arg)
|
|||||||
{
|
{
|
||||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
if (status == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||||
|
|
||||||
if (status == WAIT_FAILED)
|
|
||||||
{
|
|
||||||
error = GetLastError();
|
|
||||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (status == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
error = GetLastError();
|
||||||
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0)
|
if (status == WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
@ -664,7 +657,7 @@ static void* remdesk_server_thread(void* arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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))
|
||||||
{
|
{
|
||||||
if (BytesReturned)
|
if (BytesReturned)
|
||||||
Stream_Seek(s, BytesReturned);
|
Stream_Seek(s, BytesReturned);
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
@ -729,7 +727,7 @@ static UINT remdesk_server_start(RemdeskServerContext* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(context->priv->Thread = CreateThread(NULL, 0,
|
if (!(context->priv->Thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL)))
|
(LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
CloseHandle(context->priv->StopEvent);
|
CloseHandle(context->priv->StopEvent);
|
||||||
@ -747,34 +745,30 @@ 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)
|
||||||
{
|
{
|
||||||
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(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,35 +156,32 @@ 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,
|
||||||
NULL, /* SecurityAttributes */
|
NULL, /* SecurityAttributes */
|
||||||
CreateDisposition,
|
CreateDisposition,
|
||||||
0, /* FlagsAndAttributes */
|
0, /* FlagsAndAttributes */
|
||||||
NULL); /* TemplateFile */
|
NULL); /* TemplateFile */
|
||||||
|
|
||||||
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,
|
||||||
IoControlCode, _comm_serial_ioctl_name(IoControlCode), GetLastError());
|
"CommDeviceIoControl failure: IoControlCode=[0x%X] %s, last-error: 0x%lX",
|
||||||
|
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,8 +418,9 @@ 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, irp->MinorFunction);
|
"IRP MajorFunction: 0x%04X MinorFunction: 0x%04X\n",
|
||||||
|
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,15 +615,13 @@ 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,
|
||||||
(void*)data,
|
(void*)data,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (irpThread == INVALID_HANDLE_VALUE)
|
if (irpThread == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,18 +754,18 @@ static UINT serial_irp_request(DEVICE* device, IRP* irp)
|
|||||||
*/
|
*/
|
||||||
static UINT serial_free(DEVICE* device)
|
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,9 +776,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
@ -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,32 +910,36 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(serial->MainThread = CreateThread(NULL,
|
if (!(serial->MainThread = CreateThread(NULL,
|
||||||
0,
|
0,
|
||||||
(LPTHREAD_START_ROUTINE) serial_thread_func,
|
(LPTHREAD_START_ROUTINE) serial_thread_func,
|
||||||
(void*) serial,
|
(void*) serial,
|
||||||
0,
|
0,
|
||||||
NULL)))
|
NULL)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "CreateThread failed!");
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
error = ERROR_INTERNAL_ERROR;
|
error = ERROR_INTERNAL_ERROR;
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __linux __ */
|
#endif /* __linux __ */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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!");
|
||||||
@ -136,8 +135,9 @@ 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,8 +491,9 @@ 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,
|
||||||
irp->MajorFunction, irp->MinorFunction);
|
"Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
|
||||||
|
irp->MajorFunction, irp->MinorFunction);
|
||||||
irp->IoStatus = (UINT32)STATUS_NOT_SUPPORTED;
|
irp->IoStatus = (UINT32)STATUS_NOT_SUPPORTED;
|
||||||
|
|
||||||
if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp))
|
if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp))
|
||||||
@ -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!");
|
||||||
@ -764,24 +764,26 @@ 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,
|
||||||
|
(LPTHREAD_START_ROUTINE) smartcard_thread_func,
|
||||||
|
smartcard, CREATE_SUSPENDED, NULL);
|
||||||
|
|
||||||
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
|
|
||||||
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:
|
||||||
|
@ -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,13 +203,13 @@ 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
|
||||||
*/
|
*/
|
||||||
if (s != stream && !s->eos && s->last_start_time &&
|
if (s != stream && !s->eos && s->last_start_time &&
|
||||||
s->last_start_time < stream->last_start_time - AUDIO_TOLERANCE)
|
s->last_start_time < stream->last_start_time - AUDIO_TOLERANCE)
|
||||||
{
|
{
|
||||||
DEBUG_TSMF("Pending due to audio tolerance");
|
DEBUG_TSMF("Pending due to audio tolerance");
|
||||||
pending = TRUE;
|
pending = TRUE;
|
||||||
@ -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,11 +427,11 @@ 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);
|
||||||
|
|
||||||
if (sample->data)
|
if (sample->data)
|
||||||
{
|
{
|
||||||
@ -435,35 +441,34 @@ static BOOL tsmf_sample_playback_video(TSMF_SAMPLE* sample)
|
|||||||
* end times from the server
|
* end times from the server
|
||||||
*/
|
*/
|
||||||
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->start_time, sample->end_time, sample->duration);
|
sample->data_size, sample->extensions,
|
||||||
|
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,18 +647,19 @@ 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)
|
||||||
{
|
{
|
||||||
case TSMF_MAJOR_TYPE_VIDEO:
|
case TSMF_MAJOR_TYPE_VIDEO:
|
||||||
ret = tsmf_sample_playback_video(sample) &&
|
ret = tsmf_sample_playback_video(sample) &&
|
||||||
tsmf_sample_queue_ack(sample);
|
tsmf_sample_queue_ack(sample);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TSMF_MAJOR_TYPE_AUDIO:
|
case TSMF_MAJOR_TYPE_AUDIO:
|
||||||
ret = tsmf_sample_playback_audio(sample) &&
|
ret = tsmf_sample_playback_audio(sample) &&
|
||||||
tsmf_sample_queue_ack(sample);
|
tsmf_sample_queue_ack(sample);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -663,27 +678,30 @@ 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)
|
||||||
{
|
{
|
||||||
case TSMF_MAJOR_TYPE_VIDEO:
|
case TSMF_MAJOR_TYPE_VIDEO:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TSMF_MAJOR_TYPE_AUDIO:
|
case TSMF_MAJOR_TYPE_AUDIO:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,40 +789,42 @@ 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 &&
|
||||||
stream->sample_rate && stream->channels && stream->bits_per_sample)
|
stream->sample_rate && stream->channels && stream->bits_per_sample)
|
||||||
{
|
{
|
||||||
if (stream->decoder)
|
if (stream->decoder)
|
||||||
{
|
{
|
||||||
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;
|
||||||
@ -1295,18 +1325,19 @@ BOOL tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s)
|
|||||||
if (mediatype.MajorType == TSMF_MAJOR_TYPE_VIDEO)
|
if (mediatype.MajorType == TSMF_MAJOR_TYPE_VIDEO)
|
||||||
{
|
{
|
||||||
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.ExtraDataSize);
|
mediatype.SamplesPerSecond.Denominator,
|
||||||
|
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.ExtraDataSize);
|
mediatype.BitsPerSample,
|
||||||
|
mediatype.ExtraDataSize);
|
||||||
stream->sample_rate = mediatype.SamplesPerSecond.Numerator;
|
stream->sample_rate = mediatype.SamplesPerSecond.Numerator;
|
||||||
stream->channels = mediatype.Channels;
|
stream->channels = mediatype.Channels;
|
||||||
stream->bits_per_sample = mediatype.BitsPerSample;
|
stream->bits_per_sample = mediatype.BitsPerSample;
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user