drdynvc channel cleanup.

* Clean channel listeners on channel close
* Remove limit on listeners for channels
* Remove limit on channels
This commit is contained in:
akallabeth 2020-05-12 10:21:06 +02:00
parent 46c4b7bdc2
commit 5b2a4434d8
2 changed files with 207 additions and 199 deletions

View File

@ -30,6 +30,7 @@
#define TAG CHANNELS_TAG("drdynvc.client")
static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr);
static void dvcman_channel_free(void* channel);
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data,
UINT32 dataSize);
@ -67,64 +68,50 @@ static UINT dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
DVCMAN_LISTENER* listener;
if (dvcman->num_listeners < MAX_PLUGINS)
WLog_DBG(TAG, "create_listener: %d.%s.", ArrayList_Count(dvcman->listeners) + 1,
pszChannelName);
listener = (DVCMAN_LISTENER*)calloc(1, sizeof(DVCMAN_LISTENER));
if (!listener)
{
WLog_DBG(TAG, "create_listener: %d.%s.", dvcman->num_listeners, pszChannelName);
listener = (DVCMAN_LISTENER*)calloc(1, sizeof(DVCMAN_LISTENER));
if (!listener)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
listener->iface.GetConfiguration = dvcman_get_configuration;
listener->iface.pInterface = NULL;
listener->dvcman = dvcman;
listener->channel_name = _strdup(pszChannelName);
if (!listener->channel_name)
{
WLog_ERR(TAG, "_strdup failed!");
dvcman_wtslistener_free(listener);
return CHANNEL_RC_NO_MEMORY;
}
listener->flags = ulFlags;
listener->listener_callback = pListenerCallback;
if (ppListener)
*ppListener = (IWTSListener*)listener;
dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*)listener;
return CHANNEL_RC_OK;
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
else
listener->iface.GetConfiguration = dvcman_get_configuration;
listener->iface.pInterface = NULL;
listener->dvcman = dvcman;
listener->channel_name = _strdup(pszChannelName);
if (!listener->channel_name)
{
WLog_ERR(TAG, "create_listener: Maximum DVC listener number reached.");
WLog_ERR(TAG, "_strdup failed!");
dvcman_wtslistener_free(listener);
return CHANNEL_RC_NO_MEMORY;
}
listener->flags = ulFlags;
listener->listener_callback = pListenerCallback;
if (ppListener)
*ppListener = (IWTSListener*)listener;
if (ArrayList_Add(dvcman->listeners, listener) < 0)
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
static UINT dvcman_destroy_listener(IWTSVirtualChannelManager* pChannelMgr, IWTSListener* pListener)
{
size_t x;
DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)pListener;
WINPR_UNUSED(pChannelMgr);
if (listener)
{
DVCMAN* dvcman = listener->dvcman;
for (x = 0; x < dvcman->num_listeners; x++)
{
if (dvcman->listeners[x] == pListener)
{
size_t rest = (dvcman->num_listeners - x - 1) * sizeof(IWTSListener*);
MoveMemory(&dvcman->listeners[x], &dvcman->listeners[x + 1], rest);
dvcman->num_listeners--;
dvcman_wtslistener_free(listener);
break;
}
}
if (dvcman)
ArrayList_Remove(dvcman->listeners, listener);
}
return CHANNEL_RC_OK;
@ -140,34 +127,42 @@ static UINT dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const ch
{
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman;
if (dvcman->num_plugins < MAX_PLUGINS)
{
dvcman->plugin_names[dvcman->num_plugins] = name;
dvcman->plugins[dvcman->num_plugins++] = pPlugin;
WLog_DBG(TAG, "register_plugin: num_plugins %d", dvcman->num_plugins);
return CHANNEL_RC_OK;
}
else
{
WLog_ERR(TAG, "register_plugin: Maximum DVC plugin number %u reached.", MAX_PLUGINS);
if (ArrayList_Add(dvcman->plugin_names, _strdup(name)) < 0)
return ERROR_INTERNAL_ERROR;
}
if (ArrayList_Add(dvcman->plugins, pPlugin) < 0)
return ERROR_INTERNAL_ERROR;
WLog_DBG(TAG, "register_plugin: num_plugins %d", ArrayList_Count(dvcman->plugins));
return CHANNEL_RC_OK;
}
static IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name)
{
size_t i;
IWTSPlugin* plugin = NULL;
size_t i, nc, pc;
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman;
if (!dvcman || !pEntryPoints || !name)
return NULL;
for (i = 0; i < dvcman->num_plugins; i++)
nc = ArrayList_Count(dvcman->plugin_names);
pc = ArrayList_Count(dvcman->plugins);
if (nc != pc)
return NULL;
ArrayList_Lock(dvcman->plugin_names);
ArrayList_Lock(dvcman->plugins);
for (i = 0; i < pc; i++)
{
if (dvcman->plugin_names[i] == name || strcmp(dvcman->plugin_names[i], name) == 0)
const char* cur = ArrayList_GetItem(dvcman->plugin_names, i);
if (strcmp(cur, name) == 0)
{
return dvcman->plugins[i];
plugin = ArrayList_GetItem(dvcman->plugins, i);
break;
}
}
return NULL;
ArrayList_Unlock(dvcman->plugin_names);
ArrayList_Unlock(dvcman->plugins);
return plugin;
}
static ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
@ -196,38 +191,40 @@ static IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager*
UINT32 ChannelId)
{
int index;
BOOL found = FALSE;
DVCMAN_CHANNEL* channel;
IWTSVirtualChannel* channel = NULL;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
ArrayList_Lock(dvcman->channels);
index = 0;
channel = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index++);
while (channel)
for (index = 0; index < ArrayList_Count(dvcman->channels); index++)
{
if (channel->channel_id == ChannelId)
DVCMAN_CHANNEL* cur = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index);
if (cur->channel_id == ChannelId)
{
found = TRUE;
channel = &cur->iface;
break;
}
channel = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index++);
}
ArrayList_Unlock(dvcman->channels);
return (found) ? ((IWTSVirtualChannel*)channel) : NULL;
return channel;
}
static void dvcman_plugin_terminate(void* plugin)
{
IWTSPlugin* pPlugin = plugin;
UINT error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Terminated, pPlugin);
if (error != CHANNEL_RC_OK)
WLog_ERR(TAG, "Terminated failed with error %" PRIu32 "!", error);
}
static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
{
wObject* obj;
DVCMAN* dvcman;
dvcman = (DVCMAN*)calloc(1, sizeof(DVCMAN));
if (!dvcman)
{
WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!");
return NULL;
}
dvcman->iface.CreateListener = dvcman_create_listener;
dvcman->iface.DestroyListener = dvcman_destroy_listener;
@ -238,24 +235,36 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
dvcman->channels = ArrayList_New(TRUE);
if (!dvcman->channels)
{
WLog_Print(plugin->log, WLOG_ERROR, "ArrayList_New failed!");
free(dvcman);
return NULL;
}
goto fail;
obj = ArrayList_Object(dvcman->channels);
obj->fnObjectFree = dvcman_channel_free;
dvcman->channels->object.fnObjectFree = dvcman_channel_free;
dvcman->pool = StreamPool_New(TRUE, 10);
if (!dvcman->pool)
{
WLog_Print(plugin->log, WLOG_ERROR, "StreamPool_New failed!");
ArrayList_Free(dvcman->channels);
free(dvcman);
return NULL;
}
goto fail;
return (IWTSVirtualChannelManager*)dvcman;
dvcman->listeners = ArrayList_New(TRUE);
if (!dvcman->listeners)
goto fail;
obj = ArrayList_Object(dvcman->listeners);
obj->fnObjectFree = dvcman_wtslistener_free;
dvcman->plugin_names = ArrayList_New(TRUE);
if (!dvcman->plugin_names)
goto fail;
obj = ArrayList_Object(dvcman->plugin_names);
obj->fnObjectFree = free;
dvcman->plugins = ArrayList_New(TRUE);
if (!dvcman->plugins)
goto fail;
obj = ArrayList_Object(dvcman->plugins);
obj->fnObjectFree = dvcman_plugin_terminate;
return &dvcman->iface;
fail:
dvcman_free(plugin, &dvcman->iface);
return NULL;
}
/**
@ -304,31 +313,22 @@ static DVCMAN_CHANNEL* dvcman_channel_new(drdynvcPlugin* drdynvc,
channel = (DVCMAN_CHANNEL*)calloc(1, sizeof(DVCMAN_CHANNEL));
if (!channel)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "calloc failed!");
return NULL;
}
goto fail;
channel->dvcman = (DVCMAN*)pChannelMgr;
channel->channel_id = ChannelId;
channel->channel_name = _strdup(ChannelName);
if (!channel->channel_name)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "_strdup failed!");
free(channel);
return NULL;
}
goto fail;
if (!InitializeCriticalSectionEx(&(channel->lock), 0, 0))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "InitializeCriticalSectionEx failed!");
free(channel->channel_name);
free(channel);
return NULL;
}
goto fail;
return channel;
fail:
dvcman_channel_free(channel);
return NULL;
}
static void dvcman_channel_free(void* arg)
@ -376,31 +376,13 @@ static void dvcman_channel_free(void* arg)
static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
{
size_t i;
IWTSPlugin* pPlugin;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
UINT error;
ArrayList_Free(dvcman->listeners);
ArrayList_Free(dvcman->channels);
ArrayList_Free(dvcman->plugin_names);
ArrayList_Free(dvcman->plugins);
for (i = 0; i < dvcman->num_listeners; i++)
{
DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
dvcman_wtslistener_free(listener);
}
dvcman->num_listeners = 0;
for (i = 0; i < dvcman->num_plugins; i++)
{
pPlugin = dvcman->plugins[i];
if (pPlugin->Terminated)
if ((error = pPlugin->Terminated(pPlugin)))
WLog_Print(drdynvc->log, WLOG_ERROR, "Terminated failed with error %" PRIu32 "!",
error);
}
dvcman->num_plugins = 0;
StreamPool_Free(dvcman->pool);
free(dvcman);
}
@ -413,24 +395,26 @@ static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChan
static UINT dvcman_init(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
{
size_t i;
IWTSPlugin* pPlugin;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
UINT error;
UINT error = CHANNEL_RC_OK;
for (i = 0; i < dvcman->num_plugins; i++)
ArrayList_Lock(dvcman->plugins);
for (i = 0; i < ArrayList_Count(dvcman->plugins); i++)
{
pPlugin = dvcman->plugins[i];
IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i);
if (pPlugin->Initialize)
if ((error = pPlugin->Initialize(pPlugin, pChannelMgr)))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %" PRIu32 "!",
error);
return error;
}
error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Initialize, pPlugin, pChannelMgr);
if (error != CHANNEL_RC_OK)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %" PRIu32 "!",
error);
goto fail;
}
}
return CHANNEL_RC_OK;
fail:
ArrayList_Unlock(dvcman->plugins);
return error;
}
/**
@ -493,11 +477,13 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana
}
channel->status = ERROR_NOT_CONNECTED;
ArrayList_Add(dvcman->channels, channel);
if (ArrayList_Add(dvcman->channels, channel) < 0)
return ERROR_INTERNAL_ERROR;
for (i = 0; i < dvcman->num_listeners; i++)
ArrayList_Lock(dvcman->listeners);
for (i = 0; i < ArrayList_Count(dvcman->listeners); i++)
{
DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)ArrayList_GetItem(dvcman->listeners, i);
if (strcmp(listener->channel_name, ChannelName) == 0)
{
@ -524,7 +510,7 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana
WLog_Print(drdynvc->log, WLOG_ERROR,
"context.OnChannelConnected failed with error %" PRIu32 "", error);
return error;
goto fail;
}
else
{
@ -532,19 +518,23 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana
{
WLog_Print(drdynvc->log, WLOG_ERROR,
"OnNewChannelConnection failed with error %" PRIu32 "!", error);
return error;
goto fail;
}
else
{
WLog_Print(drdynvc->log, WLOG_ERROR,
"OnNewChannelConnection returned with bAccept FALSE!");
return ERROR_INTERNAL_ERROR;
error = ERROR_INTERNAL_ERROR;
goto fail;
}
}
}
}
error = ERROR_INTERNAL_ERROR;
fail:
ArrayList_Unlock(dvcman->listeners);
return ERROR_INTERNAL_ERROR;
return error;
}
/**
@ -590,6 +580,7 @@ static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManage
static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId,
BOOL bSendClosePDU)
{
size_t i;
DVCMAN_CHANNEL* channel;
UINT error = CHANNEL_RC_OK;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
@ -608,10 +599,10 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32
if (drdynvc && bSendClosePDU)
{
wStream* s = Stream_New(NULL, 5);
wStream* s = StreamPool_Take(dvcman->pool, 5);
if (!s)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
error = CHANNEL_RC_NO_MEMORY;
}
else
@ -619,9 +610,18 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32
Stream_Write_UINT8(s, (CLOSE_REQUEST_PDU << 4) | 0x02);
Stream_Write_UINT32(s, ChannelId);
error = drdynvc_send(drdynvc, s);
Stream_Release(s);
}
}
ArrayList_Lock(dvcman->listeners);
for (i = ArrayList_Count(dvcman->listeners); i > 0; i--)
{
DVCMAN_LISTENER* listener = ArrayList_GetItem(dvcman->listeners, i - 1);
if (strcmp(listener->channel_name, channel->channel_name) == 0)
ArrayList_Remove(dvcman->listeners, listener);
}
ArrayList_Unlock(dvcman->listeners);
ArrayList_Remove(dvcman->channels, channel);
return error;
}
@ -689,7 +689,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc,
if (channel->dvc_data)
{
/* Fragmented data */
if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data))
if (Stream_GetPosition(channel->dvc_data) + dataSize > channel->dvc_data_length)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!");
Stream_Release(channel->dvc_data);
@ -761,19 +761,17 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
switch (status)
{
case CHANNEL_RC_OK:
Stream_AddRef(s);
return CHANNEL_RC_OK;
case CHANNEL_RC_NOT_CONNECTED:
Stream_Free(s, TRUE);
return CHANNEL_RC_OK;
case CHANNEL_RC_BAD_CHANNEL_HANDLE:
Stream_Free(s, TRUE);
WLog_ERR(TAG, "VirtualChannelWriteEx failed with CHANNEL_RC_BAD_CHANNEL_HANDLE");
return status;
default:
Stream_Free(s, TRUE);
WLog_Print(drdynvc->log, WLOG_ERROR,
"VirtualChannelWriteEx failed with %s [%08" PRIX32 "]",
WTSErrorToString(status), status);
@ -795,17 +793,20 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B
UINT8 cbLen;
unsigned long chunkLength;
UINT status = CHANNEL_RC_BAD_INIT_HANDLE;
DVCMAN* dvcman;
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
dvcman = (DVCMAN*)drdynvc->channel_mgr;
WLog_Print(drdynvc->log, WLOG_DEBUG, "write_data: ChannelId=%" PRIu32 " size=%" PRIu32 "",
ChannelId, dataSize);
data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH);
data_out = StreamPool_Take(dvcman->pool, CHANNEL_CHUNK_LENGTH);
if (!data_out)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -815,7 +816,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B
if (dataSize == 0)
{
status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE);
dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE);
}
else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos)
{
@ -841,11 +842,11 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B
while (status == CHANNEL_RC_OK && dataSize > 0)
{
data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH);
data_out = StreamPool_Take(dvcman->pool, CHANNEL_CHUNK_LENGTH);
if (!data_out)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -886,12 +887,14 @@ static UINT drdynvc_send_capability_response(drdynvcPlugin* drdynvc)
{
UINT status;
wStream* s;
DVCMAN* dvcman;
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
dvcman = (DVCMAN*)drdynvc->channel_mgr;
WLog_Print(drdynvc->log, WLOG_TRACE, "capability_response");
s = Stream_New(NULL, 4);
s = StreamPool_Take(dvcman->pool, 4);
if (!s)
{
@ -1002,11 +1005,13 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int c
UINT channel_status;
char* name;
size_t length;
DVCMAN* dvcman;
WINPR_UNUSED(Sp);
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
dvcman = (DVCMAN*)drdynvc->channel_mgr;
if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES)
{
/**
@ -1039,11 +1044,11 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int c
WLog_Print(drdynvc->log, WLOG_DEBUG,
"process_create_request: ChannelId=%" PRIu32 " ChannelName=%s", ChannelId, name);
channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name);
data_out = Stream_New(NULL, pos + 4);
data_out = StreamPool_Take(dvcman->pool, pos + 4);
if (!data_out)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -1231,22 +1236,23 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
if (dataFlags & CHANNEL_FLAG_FIRST)
{
DVCMAN* mgr = (DVCMAN*)drdynvc->channel_mgr;
if (drdynvc->data_in)
Stream_Free(drdynvc->data_in, TRUE);
Stream_Release(drdynvc->data_in);
drdynvc->data_in = Stream_New(NULL, totalLength);
drdynvc->data_in = StreamPool_Take(mgr->pool, totalLength);
}
if (!(data_in = drdynvc->data_in))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
Stream_Free(drdynvc->data_in, TRUE);
Stream_Release(drdynvc->data_in);
drdynvc->data_in = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -1255,7 +1261,9 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
if (dataFlags & CHANNEL_FLAG_LAST)
{
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
const size_t cap = Stream_Capacity(data_in);
const size_t pos = Stream_GetPosition(data_in);
if (cap < pos)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_plugin_process_received: read error");
return ERROR_INVALID_DATA;
@ -1304,7 +1312,7 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam,
case CHANNEL_EVENT_WRITE_COMPLETE:
{
wStream* s = (wStream*)pData;
Stream_Free(s, TRUE);
Stream_Release(s);
}
break;
@ -1359,7 +1367,7 @@ static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg)
"drdynvc_order_recv failed with error %" PRIu32 "!", error);
}
Stream_Free(data, TRUE);
Stream_Release(data);
}
}
@ -1397,7 +1405,7 @@ static void drdynvc_queue_object_free(void* obj)
s = (wStream*)msg->wParam;
if (s)
Stream_Free(s, TRUE);
Stream_Release(s);
}
/**
@ -1529,7 +1537,7 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
if (drdynvc->data_in)
{
Stream_Free(drdynvc->data_in, TRUE);
Stream_Release(drdynvc->data_in);
drdynvc->data_in = NULL;
}
@ -1560,6 +1568,7 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc)
{
UINT error = CHANNEL_RC_OK;
size_t i;
DVCMAN* dvcman;
@ -1571,25 +1580,27 @@ static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc)
if (!dvcman)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
for (i = 0; i < dvcman->num_plugins; i++)
ArrayList_Lock(dvcman->plugins);
for (i = 0; i < ArrayList_Count(dvcman->plugins); i++)
{
UINT error;
IWTSPlugin* pPlugin = dvcman->plugins[i];
IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i);
if (pPlugin->Attached)
if ((error = pPlugin->Attached(pPlugin)))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Attach failed with error %" PRIu32 "!",
error);
return error;
}
error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Attached, pPlugin);
if (error != CHANNEL_RC_OK)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Attach failed with error %" PRIu32 "!", error);
goto fail;
}
}
return CHANNEL_RC_OK;
fail:
ArrayList_Unlock(dvcman->plugins);
return error;
}
static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc)
{
UINT error = CHANNEL_RC_OK;
size_t i;
DVCMAN* dvcman;
@ -1601,21 +1612,23 @@ static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc)
if (!dvcman)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
for (i = 0; i < dvcman->num_plugins; i++)
ArrayList_Lock(dvcman->plugins);
for (i = 0; i < ArrayList_Count(dvcman->plugins); i++)
{
UINT error;
IWTSPlugin* pPlugin = dvcman->plugins[i];
IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i);
if (pPlugin->Detached)
if ((error = pPlugin->Detached(pPlugin)))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Detach failed with error %" PRIu32 "!",
error);
return error;
}
error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Detached, pPlugin);
if (error != CHANNEL_RC_OK)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Detach failed with error %" PRIu32 "!", error);
goto fail;
}
}
return CHANNEL_RC_OK;
fail:
ArrayList_Unlock(dvcman->plugins);
return error;
}
static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,

View File

@ -37,21 +37,16 @@
typedef struct drdynvc_plugin drdynvcPlugin;
#define MAX_PLUGINS 32
struct _DVCMAN
{
IWTSVirtualChannelManager iface;
drdynvcPlugin* drdynvc;
size_t num_plugins;
const char* plugin_names[MAX_PLUGINS];
IWTSPlugin* plugins[MAX_PLUGINS];
size_t num_listeners;
IWTSListener* listeners[MAX_PLUGINS];
wArrayList* plugin_names;
wArrayList* plugins;
wArrayList* listeners;
wArrayList* channels;
wStreamPool* pool;
};