Added attach/detach support for channels.

This commit is contained in:
Armin Novak 2016-12-19 17:07:01 +01:00
parent 8d0809cf26
commit 9f19da798c
12 changed files with 446 additions and 147 deletions

View File

@ -91,6 +91,7 @@ struct _AUDIN_PLUGIN
IAudinDevice* device; IAudinDevice* device;
rdpContext* rdpcontext; rdpContext* rdpcontext;
BOOL attached;
}; };
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args); static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
@ -106,11 +107,8 @@ static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback,
wStream* out; wStream* out;
UINT32 Version; UINT32 Version;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
Stream_Read_UINT32(s, Version); Stream_Read_UINT32(s, Version);
DEBUG_DVC("Version=%"PRIu32"", Version); DEBUG_DVC("Version=%"PRIu32"", Version);
out = Stream_New(NULL, 5); out = Stream_New(NULL, 5);
if (!out) if (!out)
@ -121,9 +119,9 @@ static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback,
Stream_Write_UINT8(out, MSG_SNDIN_VERSION); Stream_Write_UINT8(out, MSG_SNDIN_VERSION);
Stream_Write_UINT32(out, Version); Stream_Write_UINT32(out, Version);
error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out), Stream_Buffer(out), NULL); error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out),
Stream_Buffer(out), NULL);
Stream_Free(out, TRUE); Stream_Free(out, TRUE);
return error; return error;
} }
@ -136,7 +134,6 @@ static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCal
{ {
BYTE out_data[1]; BYTE out_data[1];
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out_data[0] = MSG_SNDIN_DATA_INCOMING; out_data[0] = MSG_SNDIN_DATA_INCOMING;
return callback->channel->Write(callback->channel, 1, out_data, NULL); return callback->channel->Write(callback->channel, 1, out_data, NULL);
} }
@ -157,17 +154,18 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
UINT32 NumFormats; UINT32 NumFormats;
audinFormat format; audinFormat format;
UINT32 cbSizeFormatsPacket; UINT32 cbSizeFormatsPacket;
Stream_Read_UINT32(s, NumFormats); Stream_Read_UINT32(s, NumFormats);
DEBUG_DVC("NumFormats %"PRIu32"", NumFormats); DEBUG_DVC("NumFormats %"PRIu32"", NumFormats);
if ((NumFormats < 1) || (NumFormats > 1000)) if ((NumFormats < 1) || (NumFormats > 1000))
{ {
WLog_ERR(TAG, "bad NumFormats %"PRIu32"", NumFormats); WLog_ERR(TAG, "bad NumFormats %"PRIu32"", NumFormats);
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
Stream_Seek_UINT32(s); /* cbSizeFormatsPacket */
Stream_Seek_UINT32(s); /* cbSizeFormatsPacket */
callback->formats = (audinFormat*) calloc(1, NumFormats * sizeof(audinFormat)); callback->formats = (audinFormat*) calloc(1, NumFormats * sizeof(audinFormat));
if (!callback->formats) if (!callback->formats)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -198,7 +196,6 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
Stream_Read_UINT16(s, format.cbSize); Stream_Read_UINT16(s, format.cbSize);
format.data = Stream_Pointer(s); format.data = Stream_Pointer(s);
Stream_Seek(s, format.cbSize); Stream_Seek(s, format.cbSize);
DEBUG_DVC("wFormatTag=%"PRIu16" nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" " DEBUG_DVC("wFormatTag=%"PRIu16" nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" "
"nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"", "nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"",
format.wFormatTag, format.nChannels, format.nSamplesPerSec, format.wFormatTag, format.nChannels, format.nSamplesPerSec,
@ -206,16 +203,19 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
if (audin->fixed_format > 0 && audin->fixed_format != format.wFormatTag) if (audin->fixed_format > 0 && audin->fixed_format != format.wFormatTag)
continue; continue;
if (audin->fixed_channel > 0 && audin->fixed_channel != format.nChannels) if (audin->fixed_channel > 0 && audin->fixed_channel != format.nChannels)
continue; continue;
if (audin->fixed_rate > 0 && audin->fixed_rate != format.nSamplesPerSec) if (audin->fixed_rate > 0 && audin->fixed_rate != format.nSamplesPerSec)
continue; continue;
if (audin->device && audin->device->FormatSupported(audin->device, &format)) if (audin->device && audin->device->FormatSupported(audin->device, &format))
{ {
DEBUG_DVC("format ok"); DEBUG_DVC("format ok");
/* Store the agreed format in the corresponding index */ /* Store the agreed format in the corresponding index */
callback->formats[callback->formats_count++] = format; callback->formats[callback->formats_count++] = format;
/* Put the format to output buffer */ /* Put the format to output buffer */
if (!Stream_EnsureRemainingCapacity(out, 18 + format.cbSize)) if (!Stream_EnsureRemainingCapacity(out, 18 + format.cbSize))
{ {
@ -224,7 +224,6 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
goto out; goto out;
} }
Stream_Write(out, fm, 18 + format.cbSize); Stream_Write(out, fm, 18 + format.cbSize);
} }
} }
@ -237,20 +236,19 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
cbSizeFormatsPacket = (UINT32) Stream_GetPosition(out); cbSizeFormatsPacket = (UINT32) Stream_GetPosition(out);
Stream_SetPosition(out, 0); Stream_SetPosition(out, 0);
Stream_Write_UINT8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */ Stream_Write_UINT8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */
Stream_Write_UINT32(out, callback->formats_count); /* NumFormats (4 bytes) */ Stream_Write_UINT32(out, callback->formats_count); /* NumFormats (4 bytes) */
Stream_Write_UINT32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */ Stream_Write_UINT32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */
error = callback->channel->Write(callback->channel, cbSizeFormatsPacket, Stream_Buffer(out), NULL); error = callback->channel->Write(callback->channel, cbSizeFormatsPacket, Stream_Buffer(out), NULL);
out: out:
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
{ {
free(callback->formats); free(callback->formats);
callback->formats = NULL; callback->formats = NULL;
} }
Stream_Free(out, TRUE);
Stream_Free(out, TRUE);
return error; return error;
} }
@ -259,12 +257,12 @@ out:
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 NewFormat) static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback,
UINT32 NewFormat)
{ {
UINT error; UINT error;
wStream* out; wStream* out;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out = Stream_New(NULL, 5); out = Stream_New(NULL, 5);
if (!out) if (!out)
@ -277,7 +275,6 @@ static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCal
Stream_Write_UINT32(out, NewFormat); Stream_Write_UINT32(out, NewFormat);
error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL); error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL);
Stream_Free(out, TRUE); Stream_Free(out, TRUE);
return error; return error;
} }
@ -291,7 +288,6 @@ static UINT audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallba
UINT error; UINT error;
wStream* out; wStream* out;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out = Stream_New(NULL, 5); out = Stream_New(NULL, 5);
if (!out) if (!out)
@ -304,7 +300,6 @@ static UINT audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallba
Stream_Write_UINT32(out, Result); Stream_Write_UINT32(out, Result);
error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL); error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL);
Stream_Free(out, TRUE); Stream_Free(out, TRUE);
return error; return error;
} }
@ -335,9 +330,9 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data)
Stream_Write_UINT8(out, MSG_SNDIN_DATA); Stream_Write_UINT8(out, MSG_SNDIN_DATA);
Stream_Write(out, data, size); Stream_Write(out, data, size);
error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out), Stream_Buffer(out), NULL); error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out),
Stream_Buffer(out), NULL);
Stream_Free(out, TRUE); Stream_Free(out, TRUE);
return error; return error;
} }
@ -354,10 +349,8 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
UINT32 initialFormat; UINT32 initialFormat;
UINT32 FramesPerPacket; UINT32 FramesPerPacket;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
Stream_Read_UINT32(s, FramesPerPacket); Stream_Read_UINT32(s, FramesPerPacket);
Stream_Read_UINT32(s, initialFormat); Stream_Read_UINT32(s, initialFormat);
DEBUG_DVC("FramesPerPacket=%"PRIu32" initialFormat=%"PRIu32"", DEBUG_DVC("FramesPerPacket=%"PRIu32" initialFormat=%"PRIu32"",
FramesPerPacket, initialFormat); FramesPerPacket, initialFormat);
@ -369,15 +362,19 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
} }
format = &callback->formats[initialFormat]; format = &callback->formats[initialFormat];
if (audin->device) if (audin->device)
{ {
IFCALLRET(audin->device->SetFormat, error, audin->device, format, FramesPerPacket); IFCALLRET(audin->device->SetFormat, error, audin->device, format, FramesPerPacket);
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
{ {
WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error); WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error);
return error; return error;
} }
IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback); IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback);
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
{ {
WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error); WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error);
@ -409,9 +406,7 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
UINT32 NewFormat; UINT32 NewFormat;
audinFormat* format; audinFormat* format;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
Stream_Read_UINT32(s, NewFormat); Stream_Read_UINT32(s, NewFormat);
DEBUG_DVC("NewFormat=%"PRIu32"", NewFormat); DEBUG_DVC("NewFormat=%"PRIu32"", NewFormat);
if (NewFormat >= (UINT32) callback->formats_count) if (NewFormat >= (UINT32) callback->formats_count)
@ -426,18 +421,23 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
if (audin->device) if (audin->device)
{ {
IFCALLRET(audin->device->Close, error, audin->device); IFCALLRET(audin->device->Close, error, audin->device);
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
{ {
WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error); WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error);
return error; return error;
} }
IFCALLRET(audin->device->SetFormat, error, audin->device, format, 0); IFCALLRET(audin->device->SetFormat, error, audin->device, format, 0);
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
{ {
WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error); WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error);
return error; return error;
} }
IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback); IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback);
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
{ {
WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error); WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error);
@ -460,9 +460,7 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
{ {
UINT error; UINT error;
BYTE MessageId; BYTE MessageId;
Stream_Read_UINT8(data, MessageId); Stream_Read_UINT8(data, MessageId);
DEBUG_DVC("MessageId=0x%02"PRIx8"", MessageId); DEBUG_DVC("MessageId=0x%02"PRIx8"", MessageId);
switch (MessageId) switch (MessageId)
@ -502,19 +500,18 @@ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback)
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
DEBUG_DVC("..."); DEBUG_DVC("...");
if (audin->device) if (audin->device)
{ {
IFCALLRET(audin->device->Close, error, audin->device); IFCALLRET(audin->device->Close, error, audin->device);
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error); WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error);
} }
free(callback->formats); free(callback->formats);
free(callback); free(callback);
return error; return error;
} }
@ -529,10 +526,9 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
{ {
AUDIN_CHANNEL_CALLBACK* callback; AUDIN_CHANNEL_CALLBACK* callback;
AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback; AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback;
DEBUG_DVC("..."); DEBUG_DVC("...");
callback = (AUDIN_CHANNEL_CALLBACK*) calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK)); callback = (AUDIN_CHANNEL_CALLBACK*) calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK));
if (!callback) if (!callback)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -544,9 +540,7 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
callback->plugin = listener_callback->plugin; callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr; callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel; callback->channel = pChannel;
*ppCallback = (IWTSVirtualChannelCallback*) callback; *ppCallback = (IWTSVirtualChannelCallback*) callback;
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -558,10 +552,9 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{ {
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
DEBUG_DVC("..."); DEBUG_DVC("...");
audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) calloc(1, sizeof(AUDIN_LISTENER_CALLBACK)); audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) calloc(1, sizeof(AUDIN_LISTENER_CALLBACK));
if (!audin->listener_callback) if (!audin->listener_callback)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
@ -571,7 +564,6 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection; audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection;
audin->listener_callback->plugin = pPlugin; audin->listener_callback->plugin = pPlugin;
audin->listener_callback->channel_mgr = pChannelMgr; audin->listener_callback->channel_mgr = pChannelMgr;
return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0, return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0,
(IWTSListenerCallback*) audin->listener_callback, NULL); (IWTSListenerCallback*) audin->listener_callback, NULL);
} }
@ -585,32 +577,54 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin)
{ {
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
DEBUG_DVC("..."); DEBUG_DVC("...");
if (audin->device) if (audin->device)
{ {
IFCALLRET(audin->device->Free, error, audin->device); IFCALLRET(audin->device->Free, error, audin->device);
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
{ {
WLog_ERR(TAG, "Free failed with errorcode %"PRIu32"", error); WLog_ERR(TAG, "Free failed with errorcode %"PRIu32"", error);
// dont stop on error // dont stop on error
} }
audin->device = NULL; audin->device = NULL;
} }
free(audin->subsystem); free(audin->subsystem);
audin->subsystem = NULL; audin->subsystem = NULL;
free(audin->device_name); free(audin->device_name);
audin->device_name = NULL; audin->device_name = NULL;
free(audin->listener_callback); free(audin->listener_callback);
free(audin); free(audin);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
static UINT audin_plugin_attached(IWTSPlugin* pPlugin)
{
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
UINT error = CHANNEL_RC_OK;
if (!audin)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
audin->attached = TRUE;
return error;
}
static UINT audin_plugin_detached(IWTSPlugin* pPlugin)
{
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
UINT error = CHANNEL_RC_OK;
if (!audin)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
audin->attached = FALSE;
return error;
}
/** /**
* Function description * Function description
* *
@ -627,7 +641,6 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
} }
DEBUG_DVC("device registered."); DEBUG_DVC("device registered.");
audin->device = device; audin->device = device;
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -647,11 +660,13 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
if (!audin_process_addin_args(audin, args)) if (!audin_process_addin_args(audin, args))
return CHANNEL_RC_INITIALIZATION_ERROR; return CHANNEL_RC_INITIALIZATION_ERROR;
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, 0); entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL,
0);
if (entry == NULL) if (entry == NULL)
{ {
WLog_ERR(TAG, "freerdp_load_channel_addin_entry did not return any function pointers for %s ", name); WLog_ERR(TAG, "freerdp_load_channel_addin_entry did not return any function pointers for %s ",
name);
return ERROR_INVALID_FUNCTION; return ERROR_INVALID_FUNCTION;
} }
@ -679,11 +694,13 @@ static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem)
{ {
free(audin->subsystem); free(audin->subsystem);
audin->subsystem = _strdup(subsystem); audin->subsystem = _strdup(subsystem);
if (!audin->subsystem) if (!audin->subsystem)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -696,11 +713,13 @@ static UINT audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name)
{ {
free(audin->device_name); free(audin->device_name);
audin->device_name = _strdup(device_name); audin->device_name = _strdup(device_name);
if (!audin->device_name) if (!audin->device_name)
{ {
WLog_ERR(TAG, "_strdup failed!"); WLog_ERR(TAG, "_strdup failed!");
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
} }
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -725,9 +744,9 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
return TRUE; return TRUE;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
audin_args, flags, audin, NULL, NULL); audin_args, flags, audin, NULL, NULL);
if (status != 0) if (status != 0)
return FALSE; return FALSE;
@ -739,7 +758,6 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
continue; continue;
CommandLineSwitchStart(arg) CommandLineSwitchStart(arg)
CommandLineSwitchCase(arg, "sys") CommandLineSwitchCase(arg, "sys")
{ {
if ((error = audin_set_subsystem(audin, arg->Value))) if ((error = audin_set_subsystem(audin, arg->Value)))
@ -770,9 +788,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
} }
CommandLineSwitchDefault(arg) CommandLineSwitchDefault(arg)
{ {
} }
CommandLineSwitchEnd(arg) CommandLineSwitchEnd(arg)
} }
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
@ -798,7 +814,6 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
char* subsystem; char* subsystem;
char* device; char* device;
}; };
UINT error = CHANNEL_RC_INITIALIZATION_ERROR; UINT error = CHANNEL_RC_INITIALIZATION_ERROR;
ADDIN_ARGV* args; ADDIN_ARGV* args;
AUDIN_PLUGIN* audin; AUDIN_PLUGIN* audin;
@ -825,28 +840,31 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{NULL, NULL} {NULL, NULL}
}; };
struct SubsystemEntry* entry = &entries[0]; struct SubsystemEntry* entry = &entries[0];
assert(pEntryPoints); assert(pEntryPoints);
assert(pEntryPoints->GetPlugin); assert(pEntryPoints->GetPlugin);
audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin"); audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin");
if (audin != NULL) if (audin != NULL)
return CHANNEL_RC_ALREADY_INITIALIZED; return CHANNEL_RC_ALREADY_INITIALIZED;
audin = (AUDIN_PLUGIN*) calloc(1, sizeof(AUDIN_PLUGIN)); audin = (AUDIN_PLUGIN*) calloc(1, sizeof(AUDIN_PLUGIN));
if (!audin) if (!audin)
{ {
WLog_ERR(TAG, "calloc failed!"); WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
audin->attached = TRUE;
audin->iface.Initialize = audin_plugin_initialize; audin->iface.Initialize = audin_plugin_initialize;
audin->iface.Connected = NULL; audin->iface.Connected = NULL;
audin->iface.Disconnected = NULL; audin->iface.Disconnected = NULL;
audin->iface.Terminated = audin_plugin_terminated; audin->iface.Terminated = audin_plugin_terminated;
audin->iface.Attached = audin_plugin_attached;
audin->iface.Detached = audin_plugin_detached;
args = pEntryPoints->GetPluginData(pEntryPoints); args = pEntryPoints->GetPluginData(pEntryPoints);
audin->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context; audin->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(
pEntryPoints))->instance)->context;
if (args) if (args)
{ {
@ -891,8 +909,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
WLog_ERR(TAG, "no sound device."); WLog_ERR(TAG, "no sound device.");
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin); error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
out: out:
if (error != CHANNEL_RC_OK) if (error != CHANNEL_RC_OK)
audin_plugin_terminated((IWTSPlugin*)audin); audin_plugin_terminated((IWTSPlugin*)audin);

View File

@ -706,7 +706,8 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
if (status != CHANNEL_RC_OK) if (status != CHANNEL_RC_OK)
{ {
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", WTSErrorToString(status), status); WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", WTSErrorToString(status),
status);
} }
return status; return status;
@ -1379,6 +1380,64 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc)
{
int i;
DVCMAN* dvcman;
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
dvcman = (DVCMAN*) drdynvc->channel_mgr;
if (!dvcman)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
for (i = 0; i < dvcman->num_plugins; i++)
{
UINT error;
IWTSPlugin* pPlugin = dvcman->plugins[i];
if (pPlugin->Attached)
if ((error = pPlugin->Attached(pPlugin)))
{
WLog_ERR(TAG, "Attach failed with error %"PRIu32"!", error);
return error;
}
}
return CHANNEL_RC_OK;
}
static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc)
{
int i;
DVCMAN* dvcman;
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
dvcman = (DVCMAN*) drdynvc->channel_mgr;
if (!dvcman)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
for (i = 0; i < dvcman->num_plugins; i++)
{
UINT error;
IWTSPlugin* pPlugin = dvcman->plugins[i];
if (pPlugin->Detached)
if ((error = pPlugin->Detached(pPlugin)))
{
WLog_ERR(TAG, "Detach failed with error %"PRIu32"!", error);
return error;
}
}
return CHANNEL_RC_OK;
}
static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle, static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
UINT event, LPVOID pData, UINT dataLength) UINT event, LPVOID pData, UINT dataLength)
{ {
@ -1410,6 +1469,21 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam,
WLog_ERR(TAG, "drdynvc_virtual_channel_event_terminated failed with error %"PRIu32"", error); WLog_ERR(TAG, "drdynvc_virtual_channel_event_terminated failed with error %"PRIu32"", error);
break; break;
case CHANNEL_EVENT_ATTACHED:
if ((error = drdynvc_virtual_channel_event_attached(drdynvc)))
WLog_ERR(TAG, "drdynvc_virtual_channel_event_attached failed with error %"PRIu32"", error);
break;
case CHANNEL_EVENT_DETACHED:
if ((error = drdynvc_virtual_channel_event_detached(drdynvc)))
WLog_ERR(TAG, "drdynvc_virtual_channel_event_detached failed with error %"PRIu32"", error);
break;
default:
break;
} }
if (error && drdynvc->rdpcontext) if (error && drdynvc->rdpcontext)

View File

@ -742,6 +742,11 @@ static VOID VCAPITYPE rail_virtual_channel_init_event_ex(LPVOID lpUserParam, LPV
case CHANNEL_EVENT_TERMINATED: case CHANNEL_EVENT_TERMINATED:
rail_virtual_channel_event_terminated(rail); rail_virtual_channel_event_terminated(rail);
break; break;
case CHANNEL_EVENT_ATTACHED:
case CHANNEL_EVENT_DETACHED:
default:
break;
} }
if (error && rail->rdpcontext) if (error && rail->rdpcontext)

View File

@ -1738,9 +1738,10 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP
rdpdr_virtual_channel_event_terminated(rdpdr); rdpdr_virtual_channel_event_terminated(rdpdr);
break; break;
case CHANNEL_EVENT_ATTACHED:
case CHANNEL_EVENT_DETACHED:
default: default:
WLog_ERR(TAG, "unknown event %"PRIu32"!", event); WLog_ERR(TAG, "unknown event %"PRIu32"!", event);
error = ERROR_INVALID_DATA;
break; break;
} }

View File

@ -74,6 +74,8 @@ struct rdpsnd_plugin
AUDIO_FORMAT* ClientFormats; AUDIO_FORMAT* ClientFormats;
UINT16 NumberOfClientFormats; UINT16 NumberOfClientFormats;
BOOL attached;
BOOL expectingWave; BOOL expectingWave;
BYTE waveData[4]; BYTE waveData[4];
UINT16 waveDataSize; UINT16 waveDataSize;
@ -741,6 +743,9 @@ static UINT rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
Stream_Seek_UINT8(s); /* bPad */ Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize); Stream_Read_UINT16(s, BodySize);
if (!rdpsnd->attached)
goto out;
//WLog_ERR(TAG, "msgType %"PRIu8" BodySize %"PRIu16"", msgType, BodySize); //WLog_ERR(TAG, "msgType %"PRIu8" BodySize %"PRIu16"", msgType, BodySize);
switch (msgType) switch (msgType)
@ -1445,6 +1450,17 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event_ex(LPVOID lpUserParam, L
rdpsnd_virtual_channel_event_terminated(plugin); rdpsnd_virtual_channel_event_terminated(plugin);
plugin = NULL; plugin = NULL;
break; break;
case CHANNEL_EVENT_ATTACHED:
plugin->attached = TRUE;
break;
case CHANNEL_EVENT_DETACHED:
plugin->attached = FALSE;
break;
default:
break;
} }
if (error && plugin && plugin->rdpcontext) if (error && plugin && plugin->rdpcontext)
@ -1474,6 +1490,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p
return FALSE; return FALSE;
} }
rdpsnd->attached = TRUE;
#if !defined(_WIN32) && !defined(ANDROID) #if !defined(_WIN32) && !defined(ANDROID)
{ {
sigset_t mask; sigset_t mask;
@ -1497,9 +1514,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client"); rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints,
sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX));
rdpsnd->InitHandle = pInitHandle; rdpsnd->InitHandle = pInitHandle;
rc = rdpsnd->channelEntryPoints.pVirtualChannelInitEx(rdpsnd, NULL, pInitHandle, rc = rdpsnd->channelEntryPoints.pVirtualChannelInitEx(rdpsnd, NULL, pInitHandle,
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, &rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
rdpsnd_virtual_channel_init_event_ex); rdpsnd_virtual_channel_init_event_ex);

View File

@ -1015,6 +1015,11 @@ static VOID VCAPITYPE remdesk_virtual_channel_init_event_ex(LPVOID lpUserParam,
case CHANNEL_EVENT_TERMINATED: case CHANNEL_EVENT_TERMINATED:
remdesk_virtual_channel_event_terminated(remdesk); remdesk_virtual_channel_event_terminated(remdesk);
break; break;
case CHANNEL_EVENT_ATTACHED:
case CHANNEL_EVENT_DETACHED:
default:
break;
} }
if (error && remdesk->rdpcontext) if (error && remdesk->rdpcontext)

View File

@ -29,8 +29,14 @@
typedef struct _drdynvc_client_context DrdynvcClientContext; typedef struct _drdynvc_client_context DrdynvcClientContext;
typedef int (*pcDrdynvcGetVersion)(DrdynvcClientContext* context); typedef int (*pcDrdynvcGetVersion)(DrdynvcClientContext* context);
typedef UINT (*pcDrdynvcOnChannelConnected)(DrdynvcClientContext* context, const char* name, void* pInterface); typedef UINT(*pcDrdynvcOnChannelConnected)(DrdynvcClientContext* context, const char* name,
typedef UINT (*pcDrdynvcOnChannelDisconnected)(DrdynvcClientContext* context, const char* name, void* pInterface); void* pInterface);
typedef UINT(*pcDrdynvcOnChannelDisconnected)(DrdynvcClientContext* context, const char* name,
void* pInterface);
typedef UINT(*pcDrdynvcOnChannelAttached)(DrdynvcClientContext* context, const char* name,
void* pInterface);
typedef UINT(*pcDrdynvcOnChannelDetached)(DrdynvcClientContext* context, const char* name,
void* pInterface);
struct _drdynvc_client_context struct _drdynvc_client_context
{ {
@ -40,6 +46,8 @@ struct _drdynvc_client_context
pcDrdynvcGetVersion GetVersion; pcDrdynvcGetVersion GetVersion;
pcDrdynvcOnChannelConnected OnChannelConnected; pcDrdynvcOnChannelConnected OnChannelConnected;
pcDrdynvcOnChannelDisconnected OnChannelDisconnected; pcDrdynvcOnChannelDisconnected OnChannelDisconnected;
pcDrdynvcOnChannelAttached OnChannelAttached;
pcDrdynvcOnChannelDetached OnChannelDetached;
}; };
#endif /* FREERDP_CHANNEL_CLIENT_DRDYNVC_H */ #endif /* FREERDP_CHANNEL_CLIENT_DRDYNVC_H */

View File

@ -116,6 +116,10 @@ struct _IWTSPlugin
has terminated. */ has terminated. */
UINT(*Terminated)(IWTSPlugin* pPlugin); UINT(*Terminated)(IWTSPlugin* pPlugin);
UINT(*Attached)(IWTSPlugin* pPlugin);
UINT(*Detached)(IWTSPlugin* pPlugin);
/* Extended */ /* Extended */
void* pInterface; void* pInterface;

View File

@ -84,6 +84,16 @@ DEFINE_EVENT_BEGIN(ChannelDisconnected)
void* pInterface; void* pInterface;
DEFINE_EVENT_END(ChannelDisconnected) DEFINE_EVENT_END(ChannelDisconnected)
DEFINE_EVENT_BEGIN(ChannelAttached)
const char* name;
void* pInterface;
DEFINE_EVENT_END(ChannelAttached)
DEFINE_EVENT_BEGIN(ChannelDetached)
const char* name;
void* pInterface;
DEFINE_EVENT_END(ChannelDetached)
DEFINE_EVENT_BEGIN(MouseEvent) DEFINE_EVENT_BEGIN(MouseEvent)
UINT16 flags; UINT16 flags;
UINT16 x; UINT16 x;

View File

@ -307,13 +307,22 @@ FREERDP_API BOOL freerdp_shall_disconnect(freerdp* instance);
FREERDP_API BOOL freerdp_disconnect(freerdp* instance); FREERDP_API BOOL freerdp_disconnect(freerdp* instance);
FREERDP_API BOOL freerdp_reconnect(freerdp* instance); FREERDP_API BOOL freerdp_reconnect(freerdp* instance);
FREERDP_API UINT freerdp_channel_add_init_handle_data(rdpChannelHandles* handles, void* pInitHandle, void* pUserData); FREERDP_API UINT freerdp_channel_add_init_handle_data(rdpChannelHandles* handles, void* pInitHandle,
FREERDP_API void* freerdp_channel_get_init_handle_data(rdpChannelHandles* handles, void* pInitHandle); void* pUserData);
FREERDP_API void freerdp_channel_remove_init_handle_data(rdpChannelHandles* handles, void* pInitHandle); FREERDP_API void* freerdp_channel_get_init_handle_data(rdpChannelHandles* handles,
void* pInitHandle);
FREERDP_API void freerdp_channel_remove_init_handle_data(rdpChannelHandles* handles,
void* pInitHandle);
FREERDP_API UINT freerdp_channel_add_open_handle_data(rdpChannelHandles* handles, DWORD openHandle, void* pUserData); FREERDP_API UINT freerdp_channel_add_open_handle_data(rdpChannelHandles* handles, DWORD openHandle,
FREERDP_API void* freerdp_channel_get_open_handle_data(rdpChannelHandles* handles, DWORD openHandle); void* pUserData);
FREERDP_API void freerdp_channel_remove_open_handle_data(rdpChannelHandles* handles, DWORD openHandle); FREERDP_API void* freerdp_channel_get_open_handle_data(rdpChannelHandles* handles,
DWORD openHandle);
FREERDP_API void freerdp_channel_remove_open_handle_data(rdpChannelHandles* handles,
DWORD openHandle);
FREERDP_API UINT freerdp_channels_attach(freerdp* instance);
FREERDP_API UINT freerdp_channels_detach(freerdp* instance);
FREERDP_API BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, FREERDP_API BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount,
void** wfds, int* wcount); void** wfds, int* wcount);

View File

@ -182,6 +182,36 @@ static UINT freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext*
return status; return status;
} }
static UINT freerdp_drdynvc_on_channel_attached(DrdynvcClientContext*
context,
const char* name, void* pInterface)
{
UINT status = CHANNEL_RC_OK;
ChannelAttachedEventArgs e;
rdpChannels* channels = (rdpChannels*) context->custom;
freerdp* instance = channels->instance;
EventArgsInit(&e, "freerdp");
e.name = name;
e.pInterface = pInterface;
PubSub_OnChannelAttached(instance->context->pubSub, instance->context, &e);
return status;
}
static UINT freerdp_drdynvc_on_channel_detached(DrdynvcClientContext*
context,
const char* name, void* pInterface)
{
UINT status = CHANNEL_RC_OK;
ChannelDetachedEventArgs e;
rdpChannels* channels = (rdpChannels*) context->custom;
freerdp* instance = channels->instance;
EventArgsInit(&e, "freerdp");
e.name = name;
e.pInterface = pInterface;
PubSub_OnChannelDetached(instance->context->pubSub, instance->context, &e);
return status;
}
/** /**
* go through and inform all the libraries that we are initialized * go through and inform all the libraries that we are initialized
* called only from main thread * called only from main thread
@ -214,6 +244,122 @@ UINT freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance)
return error; return error;
} }
UINT freerdp_channels_attach(freerdp* instance)
{
UINT error = CHANNEL_RC_OK;
int index;
char* name = NULL;
char* hostname;
int hostnameLength;
rdpChannels* channels;
CHANNEL_CLIENT_DATA* pChannelClientData;
channels = instance->context->channels;
channels->connected = 1;
hostname = instance->settings->ServerHostname;
hostnameLength = (int) strlen(hostname);
for (index = 0; index < channels->clientDataCount; index++)
{
ChannelConnectedEventArgs e;
CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
pChannelClientData = &channels->clientDataList[index];
if (pChannelClientData->pChannelInitEventProc)
{
pChannelClientData->pChannelInitEventProc(
pChannelClientData->pInitHandle, CHANNEL_EVENT_ATTACHED, hostname, hostnameLength);
}
else if (pChannelClientData->pChannelInitEventProcEx)
{
pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
pChannelClientData->pInitHandle, CHANNEL_EVENT_ATTACHED, hostname, hostnameLength);
}
if (getChannelError(instance->context) != CHANNEL_RC_OK)
goto fail;
pChannelOpenData = &channels->openDataList[index];
name = (char*) malloc(9);
if (!name)
{
error = CHANNEL_RC_NO_MEMORY;
goto fail;
}
CopyMemory(name, pChannelOpenData->name, 8);
name[8] = '\0';
EventArgsInit(&e, "freerdp");
e.name = name;
e.pInterface = pChannelOpenData->pInterface;
PubSub_OnChannelAttached(instance->context->pubSub, instance->context, &e);
free(name);
name = NULL;
}
fail:
free(name);
return error;
}
UINT freerdp_channels_detach(freerdp* instance)
{
UINT error = CHANNEL_RC_OK;
int index;
char* name = NULL;
char* hostname;
int hostnameLength;
rdpChannels* channels;
CHANNEL_CLIENT_DATA* pChannelClientData;
channels = instance->context->channels;
channels->connected = 1;
hostname = instance->settings->ServerHostname;
hostnameLength = (int) strlen(hostname);
for (index = 0; index < channels->clientDataCount; index++)
{
ChannelConnectedEventArgs e;
CHANNEL_OPEN_DATA* pChannelOpenData;
pChannelClientData = &channels->clientDataList[index];
if (pChannelClientData->pChannelInitEventProc)
{
pChannelClientData->pChannelInitEventProc(
pChannelClientData->pInitHandle, CHANNEL_EVENT_DETACHED, hostname, hostnameLength);
}
else if (pChannelClientData->pChannelInitEventProcEx)
{
pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
pChannelClientData->pInitHandle, CHANNEL_EVENT_DETACHED, hostname, hostnameLength);
}
if (getChannelError(instance->context) != CHANNEL_RC_OK)
goto fail;
pChannelOpenData = &channels->openDataList[index];
name = (char*) malloc(9);
if (!name)
{
error = CHANNEL_RC_NO_MEMORY;
goto fail;
}
CopyMemory(name, pChannelOpenData->name, 8);
name[8] = '\0';
EventArgsInit(&e, "freerdp");
e.name = name;
e.pInterface = pChannelOpenData->pInterface;
PubSub_OnChannelDetached(instance->context->pubSub, instance->context, &e);
free(name);
name = NULL;
}
fail:
free(name);
return error;
}
/** /**
* go through and inform all the libraries that we are connected * go through and inform all the libraries that we are connected
* this will tell the libraries that its ok to call MyVirtualChannelOpen * this will tell the libraries that its ok to call MyVirtualChannelOpen
@ -234,7 +380,7 @@ UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
for (index = 0; index < channels->clientDataCount; index++) for (index = 0; index < channels->clientDataCount; index++)
{ {
ChannelConnectedEventArgs e; ChannelConnectedEventArgs e;
CHANNEL_OPEN_DATA* pChannelOpenData = NULL; CHANNEL_OPEN_DATA* pChannelOpenData;
pChannelClientData = &channels->clientDataList[index]; pChannelClientData = &channels->clientDataList[index];
if (pChannelClientData->pChannelInitEventProc) if (pChannelClientData->pChannelInitEventProc)
@ -279,6 +425,8 @@ UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
channels->drdynvc->OnChannelConnected = freerdp_drdynvc_on_channel_connected; channels->drdynvc->OnChannelConnected = freerdp_drdynvc_on_channel_connected;
channels->drdynvc->OnChannelDisconnected = channels->drdynvc->OnChannelDisconnected =
freerdp_drdynvc_on_channel_disconnected; freerdp_drdynvc_on_channel_disconnected;
channels->drdynvc->OnChannelAttached = freerdp_drdynvc_on_channel_attached;
channels->drdynvc->OnChannelDetached = freerdp_drdynvc_on_channel_detached;
} }
fail: fail:

View File

@ -133,6 +133,8 @@ typedef CHANNEL_INIT_EVENT_EX_FN* PCHANNEL_INIT_EVENT_EX_FN;
#define CHANNEL_EVENT_TERMINATED 4 #define CHANNEL_EVENT_TERMINATED 4
#define CHANNEL_EVENT_REMOTE_CONTROL_START 5 #define CHANNEL_EVENT_REMOTE_CONTROL_START 5
#define CHANNEL_EVENT_REMOTE_CONTROL_STOP 6 #define CHANNEL_EVENT_REMOTE_CONTROL_STOP 6
#define CHANNEL_EVENT_ATTACHED 7
#define CHANNEL_EVENT_DETACHED 8
#define CHANNEL_EVENT_DATA_RECEIVED 10 #define CHANNEL_EVENT_DATA_RECEIVED 10
#define CHANNEL_EVENT_WRITE_COMPLETE 11 #define CHANNEL_EVENT_WRITE_COMPLETE 11
#define CHANNEL_EVENT_WRITE_CANCELLED 12 #define CHANNEL_EVENT_WRITE_CANCELLED 12