static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { UINT32 ChannelId; wStream* data_out; int value; int error; ChannelId = drdynvc_read_variable_uint(s, cbChId); DEBUG_DVC("ChannelId=%d", ChannelId); dvcman_close_channel(drdynvc->channel_mgr, ChannelId); data_out = Stream_New(NULL, 4); value = (CLOSE_REQUEST_PDU << 4) | (cbChId & 0x03); Stream_Write_UINT8(data_out, value); drdynvc_write_variable_uint(data_out, ChannelId); error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); if (error != CHANNEL_RC_OK) { DEBUG_WARN("VirtualChannelWrite failed %d", error); return 1; } drdynvc->channel_error = error; return 0; }
static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* data_in) { uint32 ChannelId; ChannelId = drdynvc_read_variable_uint(data_in, cbChId); DEBUG_DVC("ChannelId=%d", ChannelId); dvcman_close_channel(drdynvc->channel_mgr, ChannelId); return 0; }
static int process_CLOSE_REQUEST_PDU(drdynvcPlugin * plugin, int Sp, int cbChId, char * data, int data_size) { int pos; uint32 ChannelId; pos = 1; ChannelId = get_variable_uint(cbChId, data, &pos); LLOGLN(10, ("process_CLOSE_REQUEST_PDU: ChannelId=%d", ChannelId)); dvcman_close_channel(plugin->channel_mgr, ChannelId); return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { int value; UINT error; UINT32 ChannelId; wStream* data_out; if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId)) return ERROR_INVALID_DATA; ChannelId = drdynvc_read_variable_uint(s, cbChId); WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp, cbChId, ChannelId); if ((error = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) { WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_channel failed with error %"PRIu32"!", error); return error; } data_out = Stream_New(NULL, 4); if (!data_out) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } value = (CLOSE_REQUEST_PDU << 4) | (cbChId & 0x03); Stream_Write_UINT8(data_out, value); drdynvc_write_variable_uint(data_out, ChannelId); error = drdynvc_send(drdynvc, data_out); if (error) WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", WTSErrorToString(error), error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { int value; UINT error; UINT32 ChannelId; wStream* data_out; ChannelId = drdynvc_read_variable_uint(s, cbChId); WLog_DBG(TAG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%d", Sp, cbChId, ChannelId); if ((error = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) { WLog_ERR(TAG, "dvcman_close_channel failed with error %lu!", error); return error; } data_out = Stream_New(NULL, 4); if (!data_out) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } value = (CLOSE_REQUEST_PDU << 4) | (cbChId & 0x03); Stream_Write_UINT8(data_out, value); drdynvc_write_variable_uint(data_out, ChannelId); error = drdynvc_send(drdynvc, data_out); if (error) WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(error), error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { size_t pos; UINT status; UINT32 ChannelId; wStream* data_out; UINT channel_status; char* name; size_t length; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) { /** * For some reason the server does not always send the * capabilities pdu as it should. When this happens, * send a capabilities response. */ drdynvc->version = 3; if ((status = drdynvc_send_capability_response(drdynvc))) { WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_send_capability_response failed!"); return status; } drdynvc->state = DRDYNVC_STATE_READY; } if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId)) return ERROR_INVALID_DATA; ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); name = (char*)Stream_Pointer(s); length = Stream_GetRemainingLength(s); if (strnlen(name, length) >= length) return ERROR_INVALID_DATA; 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); if (!data_out) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(s, data_out, pos - 1); if (channel_status == CHANNEL_RC_OK) { WLog_Print(drdynvc->log, WLOG_DEBUG, "channel created"); Stream_Write_UINT32(data_out, 0); } else { WLog_Print(drdynvc->log, WLOG_DEBUG, "no listener"); Stream_Write_UINT32(data_out, (UINT32)0xC0000001); /* same code used by mstsc */ } status = drdynvc_send(drdynvc, data_out); if (status != CHANNEL_RC_OK) { WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", WTSErrorToString(status), status); return status; } if (channel_status == CHANNEL_RC_OK) { if ((status = dvcman_open_channel(drdynvc, drdynvc->channel_mgr, ChannelId))) { WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_open_channel failed with error %"PRIu32"!", status); return status; } } else { if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_channel failed with error %"PRIu32"!", status); } return status; }
static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; UINT error = CHANNEL_RC_OK; drdynvcPlugin* drdynvc = (drdynvcPlugin*) arg; if (!drdynvc) { ExitThread((DWORD) CHANNEL_RC_BAD_CHANNEL_HANDLE); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } while (1) { if (!MessageQueue_Wait(drdynvc->queue)) { WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Wait failed!"); error = ERROR_INTERNAL_ERROR; break; } if (!MessageQueue_Peek(drdynvc->queue, &message, TRUE)) { WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Peek failed!"); error = ERROR_INTERNAL_ERROR; break; } if (message.id == WMQ_QUIT) break; if (message.id == 0) { data = (wStream*) message.wParam; if ((error = drdynvc_order_recv(drdynvc, data))) { Stream_Free(data, TRUE); WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_order_recv failed with error %"PRIu32"!", error); break; } Stream_Free(data, TRUE); } } { /* Disconnect remaining dynamic channels that the server did not. * This is required to properly shut down channels by calling the appropriate * event handlers. */ DVCMAN* drdynvcMgr = (DVCMAN*)drdynvc->channel_mgr; while (ArrayList_Count(drdynvcMgr->channels) > 0) { IWTSVirtualChannel* channel = (IWTSVirtualChannel*) ArrayList_GetItem(drdynvcMgr->channels, 0); const UINT32 ChannelId = drdynvc->channel_mgr->GetChannelId(channel); dvcman_close_channel(drdynvc->channel_mgr, ChannelId); } } if (error && drdynvc->rdpcontext) setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_client_thread reported an error"); ExitThread((DWORD) error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { unsigned long pos; UINT status; UINT32 ChannelId; wStream* data_out; UINT channel_status; if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) { /** * For some reason the server does not always send the * capabilities pdu as it should. When this happens, * send a capabilities response. */ drdynvc->version = 3; if ((status = drdynvc_send_capability_response(drdynvc))) { WLog_ERR(TAG, "drdynvc_send_capability_response failed!"); return status; } drdynvc->state = DRDYNVC_STATE_READY; } ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); WLog_DBG(TAG, "process_create_request: ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); data_out = Stream_New(NULL, pos + 4); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(s, data_out, pos - 1); if (channel_status == CHANNEL_RC_OK) { WLog_DBG(TAG, "channel created"); Stream_Write_UINT32(data_out, 0); } else { WLog_DBG(TAG, "no listener"); Stream_Write_UINT32(data_out, (UINT32) 0xC0000001); /* same code used by mstsc */ } status = drdynvc_send(drdynvc, data_out); if (status != CHANNEL_RC_OK) { WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(status), status); return status; } if (channel_status == CHANNEL_RC_OK) { if ((status = dvcman_open_channel(drdynvc->channel_mgr, ChannelId))) { WLog_ERR(TAG, "dvcman_open_channel failed with error %lu!", status); return status; } } else { if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) WLog_ERR(TAG, "dvcman_close_channel failed with error %lu!", status); } return status; }