int rdp8_decompress(void *handle, const char *cdata, int cdata_bytes, int flags, char **data, int *data_bytes) { struct bulk_rdp8 *bulk; byte descriptor; uint16 segmentCount; uint32 uncompressedSize; uint32 segmentOffset; byte *pConcatenated; uint16 segmentNumber; uint32 size; const byte *lcdata; bulk = (struct bulk_rdp8 *) handle; if (bulk == NULL) { return 1; } if ((flags & NL_COMPRESSION_TYPE_MASK) != NL_PACKET_COMPR_TYPE_RDP8) { return 0; } descriptor = GGET_UINT8(cdata, 0); if (descriptor == SEGMENTED_SINGLE) { lcdata = (const byte *) (cdata + 1); if (OutputFromSegment(bulk, lcdata, cdata_bytes - 1) != 0) { return 1; } *data = (char *) malloc(bulk->m_outputCount); *data_bytes = bulk->m_outputCount; memcpy(*data, bulk->m_outputBuffer, bulk->m_outputCount); } else if (descriptor == SEGMENTED_MULTIPART) { segmentCount = GGET_UINT16(cdata, 1); uncompressedSize = GGET_UINT32(cdata, 3); segmentOffset = 7; pConcatenated = (byte *) malloc(uncompressedSize); *data = (char *) pConcatenated; *data_bytes = uncompressedSize; for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++) { size = GGET_UINT32(cdata, segmentOffset); lcdata = (const byte *) (cdata + segmentOffset + 4); if (OutputFromSegment(bulk, lcdata, size) != 0) { return 1; } segmentOffset += 4 + size; memcpy(pConcatenated, bulk->m_outputBuffer, bulk->m_outputCount); pConcatenated += bulk->m_outputCount; } } else { return 1; } return 0; }
/* * called when WTSVirtualChannelOpenEx is invoked in xrdpapi.c * ******************************************************************************/ int DEFAULT_CC my_api_trans_conn_in(struct trans *trans, struct trans *new_trans) { struct xrdp_api_data *ad; struct stream *s; int error; int index; char chan_pri; if ((trans == 0) || (trans != g_api_lis_trans) || (new_trans == 0)) { return 1; } LOGM((LOG_LEVEL_DEBUG, "my_api_trans_conn_in:")); LOG(10, ("my_api_trans_conn_in: got incoming")); s = trans_get_in_s(new_trans); s->end = s->data; error = trans_force_read(new_trans, 64); if (error != 0) { LOG(0, ("my_api_trans_conn_in: trans_force_read failed")); trans_delete(new_trans); } s->end = s->data; ad = (struct xrdp_api_data *) g_malloc(sizeof(struct xrdp_api_data), 1); g_memcpy(ad->header, s->data, 64); ad->flags = GGET_UINT32(ad->header, 16); ad->chan_id = -1; ad->dvc_chan_id = -1; if (ad->flags > 0) { /* opening a dynamic virtual channel */ if ((index = find_empty_slot_in_dvc_channels()) < 0) { /* exceeded MAX_DVC_CHANNELS */ LOG(0, ("my_api_trans_conn_in: MAX_DVC_CHANNELS reached; giving up!")) g_free(ad); trans_delete(new_trans); return 1; } g_dvc_channels[index] = ad; chan_pri = 4 - ad->flags; ad->dvc_chan_id = g_dvc_chan_id++; ad->is_connected = 0; ad->transp = new_trans; drdynvc_send_open_channel_request(chan_pri, ad->dvc_chan_id, ad->header); } else { /* opening a static virtual channel */ for (index = 0; index < g_num_chan_items; index++) { LOG(10, ("my_api_trans_conn_in: %s %s", ad->header, g_chan_items[index].name)); if (g_strcasecmp(ad->header, g_chan_items[index].name) == 0) { LOG(10, ("my_api_trans_conn_in: found it at %d", index)); ad->chan_id = g_chan_items[index].id; break; } } if (index == g_num_chan_items) { g_writeln("did not find SVC named %s", ad->header); } } new_trans->callback_data = ad; trans_delete(g_api_con_trans); g_api_con_trans = new_trans; g_api_con_trans->trans_data_in = my_api_trans_data_in; g_api_con_trans->header_size = 0; return 0; }