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;
}
示例#2
0
文件: chansrv.c 项目: eric011/xrdp
/*
 * 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;
}