size_t str(char * buffer, size_t sz, const RDPOrderCommon & common) const
    {
        size_t lg = common.str(buffer, sz, true);

        lg += snprintf(
            buffer+lg,
            sz-lg,
            "lineto(back_mode=%.2x "
                "startx=%d starty=%d endx=%d endy=%d "
                "rop2=%d back_color=%.6x"
                "pen.style=%d pen.width=%d pen.color=%.6x "
                "\n",
            unsigned(this->back_mode),
            this->startx, this->starty, this->endx, this->endy,
            this->rop2,
            this->back_color.as_bgr().to_u32(),
            this->pen.style,
            this->pen.width,
            this->pen.color.as_bgr().to_u32()
            );
        if (lg >= sz){
            return sz;
        }
        return lg;
    }
 size_t str(char * buffer, size_t sz, const RDPOrderCommon & common) const {
     size_t lg = 0;
     lg += common.str(buffer + lg, sz - lg, true);
     lg += snprintf(buffer + lg, sz - lg,
                    "polygoncb(xStart=%d yStart=%d bRop2=0x%02X fillMode=%d "
                    "backColor=%.6x foreColor=%.6x "
                    "brush.org_x=%d brush.org_y=%d "
                    "brush.style=%d brush.hatch=%d "
                    "NumDeltaEntries=%d DeltaEntries=(",
                    this->xStart, this->yStart, unsigned(this->bRop2), this->fillMode,
                    this->backColor.as_bgr().to_u32(), this->foreColor.as_bgr().to_u32(),
                    this->brush.org_x, this->brush.org_y,
                    this->brush.style, this->brush.hatch,
                    this->NumDeltaEntries);
     for (uint8_t i = 0; i < this->NumDeltaEntries; i++) {
         if (i) {
             lg += snprintf(buffer + lg, sz - lg, " ");
         }
         lg += snprintf(buffer + lg, sz - lg, "(%d, %d)", this->deltaPoints[i].xDelta, this->deltaPoints[i].yDelta);
     }
     lg += snprintf(buffer + lg, sz - lg, "))");
     if (lg >= sz) {
         return sz;
     }
     return lg;
 }
    void emit(Stream & stream,
                RDPOrderCommon & common,
                const RDPOrderCommon & oldcommon,
                const RDPScrBlt & oldcmd) const
    {
        using namespace RDP;
        RDPPrimaryOrderHeader header(STANDARD, 0);

        if (!common.clip.contains(this->rect)){
            header.control |= BOUNDS;
        }

        // SCREENBLT fields bytes (1 byte)
        // ------------------------------
        // 0x01: x coordinate
        // 0x02: y coordinate
        // 0x04: cx coordinate
        // 0x08: cy coordinate
        // 0x10: rop byte
        // 0x20: srcx coordinate
        // 0x40: srcy coordinate

        DeltaRect dr(this->rect, oldcmd.rect);

        // RDP specs says that we can have DELTA only if we
        // have bounds. Can't see the rationale and rdesktop don't do it
        // by the book. Behavior should be checked with server and clients
        // from Microsoft. Looks like an error in RDP specs.
        header.control |= ((dr.fully_relative()
                   && is_1_byte(this->srcx - oldcmd.srcx)
                   && is_1_byte(this->srcy - oldcmd.srcy))
                                                          * DELTA);

        header.fields = (dr.dleft     != 0               ) * 0x01
                      | (dr.dtop      != 0               ) * 0x02
                      | (dr.dwidth    != 0               ) * 0x04
                      | (dr.dheight   != 0               ) * 0x08
                      | (this->rop    != oldcmd.rop      ) * 0x10
                      | ((this->srcx - oldcmd.srcx) != 0 ) * 0x20
                      | ((this->srcy - oldcmd.srcy) != 0 ) * 0x40
                      ;

        common.emit(stream, header, oldcommon);

        header.emit_rect(stream, 0x01, this->rect, oldcmd.rect);

        if (header.fields & 0x10){
            stream.out_uint8(this->rop);
        }

        header.emit_src(stream, 0x20,
                        this->srcx, this->srcy,
                        oldcmd.srcx, oldcmd.srcy);

    }
    void emit( Stream & stream, RDPOrderCommon & common, const RDPOrderCommon & oldcommon
             , const RDPMultiOpaqueRect & oldcmd) const {
        RDPPrimaryOrderHeader header(RDP::STANDARD, 0);

        int16_t nLeftRect = 0;
        int16_t nTopRect  = 0;
        int16_t nWidth    = 0;
        int16_t nHeight   = 0;
        if (!common.clip.contains(Rect(nLeftRect, nTopRect, nWidth, nHeight))) {
            header.control |= RDP::BOUNDS;
        }
        else {
            for (uint8_t i = 0; i < this->nDeltaEntries; i++) {
                nLeftRect += this->deltaEncodedRectangles[i].leftDelta;
                nTopRect  += this->deltaEncodedRectangles[i].topDelta;
                nWidth    =  this->deltaEncodedRectangles[i].width;
                nHeight   =  this->deltaEncodedRectangles[i].height;

                if (!common.clip.contains(Rect(nLeftRect, nTopRect, nWidth, nHeight))) {
                    header.control |= RDP::BOUNDS;
                    break;
                }
            }
        }

        header.control |= (is_1_byte(this->nLeftRect - oldcmd.nLeftRect) && is_1_byte(this->nTopRect - oldcmd.nTopRect) &&
            is_1_byte(this->nWidth - oldcmd.nWidth) && is_1_byte(this->nHeight - oldcmd.nHeight)) * RDP::DELTA;

        header.fields =
                (this->nLeftRect           != oldcmd.nLeftRect          ) * 0x0001
              | (this->nTopRect            != oldcmd.nTopRect           ) * 0x0002
              | (this->nWidth              != oldcmd.nWidth             ) * 0x0004
              | (this->nHeight             != oldcmd.nHeight            ) * 0x0008
              | ((this->_Color & 0x0000FF) != (oldcmd._Color & 0x0000FF)) * 0x0010
              | ((this->_Color & 0x00FF00) != (oldcmd._Color & 0x00FF00)) * 0x0020
              | ((this->_Color & 0xFF0000) != (oldcmd._Color & 0xFF0000)) * 0x0040
              | (this->nDeltaEntries       != oldcmd.nDeltaEntries      ) * 0x0080
              | (
                 (this->nDeltaEntries != oldcmd.nDeltaEntries) ||
                 memcmp(this->deltaEncodedRectangles, oldcmd.deltaEncodedRectangles,
                        this->nDeltaEntries * sizeof(RDP::DeltaEncodedRectangle))
                                                                        ) * 0x0100
              ;

        common.emit(stream, header, oldcommon);

        header.emit_coord(stream, 0x0001, this->nLeftRect, oldcmd.nLeftRect);
        header.emit_coord(stream, 0x0002, this->nTopRect,  oldcmd.nTopRect);
        header.emit_coord(stream, 0x0004, this->nWidth,    oldcmd.nWidth);
        header.emit_coord(stream, 0x0008, this->nHeight,   oldcmd.nHeight);

        if (header.fields & 0x0010) { stream.out_uint8(this->_Color); }
        if (header.fields & 0x0020) { stream.out_uint8(this->_Color >> 8); }
 size_t str(char * buffer, size_t sz, const RDPOrderCommon & common) const {
     size_t lg = 0;
     lg += common.str(buffer + lg, sz - lg, true);
     lg += snprintf(buffer + lg, sz - lg,
         "ellipseSC(leftRect=%d topRect=%d rightRect=%d bottomRect=%d bRop2=0x%02X "
         "fillMode=%d Color=%.6x)",
                    this->el.left(), this->el.top(), this->el.right(), this->el.bottom(),
                    unsigned(this->bRop2), this->fillMode, this->color.as_bgr().to_u32());
     if (lg >= sz) {
         return sz;
     }
     return lg;
 }
 size_t str(char * buffer, size_t sz, const RDPOrderCommon & common) const
 {
     size_t lg = common.str(buffer, sz);
     lg += snprintf(
         buffer+lg,
         sz-lg,
         "scrblt(rect(%d,%d,%d,%d) rop=%x srcx=%d srcy=%d)\n",
         this->rect.x, this->rect.y, this->rect.cx, this->rect.cy,
         this->rop, this->srcx, this->srcy);
     if (lg >= sz){
         return sz;
     }
     return lg;
 }
 size_t str(char * buffer, size_t sz, const RDPOrderCommon & common) const
 {
     size_t lg = common.str(buffer, sz, !common.clip.contains(this->rect));
     lg += snprintf(
         buffer+lg,
         sz-lg,
         "destblt(rect(%d,%d,%d,%d) rop=%x)\n",
         this->rect.x, this->rect.y, this->rect.cx, this->rect.cy,
         this->rop);
     if (lg >= sz){
         return sz;
     }
     return lg;
 }
    void emit(OutStream & stream,
            RDPOrderCommon & common,
            const RDPOrderCommon & oldcommon,
            const RDPLineTo & oldcmd) const
    {
        using namespace RDP;
        RDPPrimaryOrderHeader header(STANDARD, 0);

        // TODO check that
        if (!(common.clip.contains_pt(this->startx, this->starty)
           && common.clip.contains_pt(this->endx, this->endy))){
           header.control |= BOUNDS;
        }

        header.control |= (is_1_byte(this->startx - oldcmd.startx)
                 && is_1_byte(this->starty - oldcmd.starty)
                 && is_1_byte(this->endx - oldcmd.endx)
                 && is_1_byte(this->endy - oldcmd.endy)) * DELTA;

        header.fields =
                (this->back_mode  != oldcmd.back_mode  ) * 0x001
              | (this->startx     != oldcmd.startx     ) * 0x002
              | (this->starty     != oldcmd.starty     ) * 0x004
              | (this->endx       != oldcmd.endx       ) * 0x008
              | (this->endy       != oldcmd.endy       ) * 0x010
              | (this->back_color != oldcmd.back_color ) * 0x020
              | (this->rop2       != oldcmd.rop2       ) * 0x040
              | (this->pen.style  != oldcmd.pen.style  ) * 0x080
              | (this->pen.width  != oldcmd.pen.width  ) * 0x100
              | (this->pen.color  != oldcmd.pen.color  ) * 0x200
              ;

        common.emit(stream, header, oldcommon);

        if (header.fields & 0x001) { stream.out_uint16_le(this->back_mode); }

        header.emit_coord(stream, 0x02, this->startx, oldcmd.startx);
        header.emit_coord(stream, 0x04, this->starty, oldcmd.starty);
        header.emit_coord(stream, 0x08, this->endx,   oldcmd.endx);
        header.emit_coord(stream, 0x10, this->endy,   oldcmd.endy);

        if (header.fields & 0x20) {
            emit_rdp_color(stream, this->back_color);
        }
        if (header.fields & 0x40) { stream.out_uint8(this->rop2); }
        header.emit_pen(stream, 0x80, this->pen, oldcmd.pen);
    }
    void emit(OutStream & stream, RDPOrderCommon & common, const RDPOrderCommon & oldcommon,
              const RDPEllipseSC & oldcmd) const {
        RDPPrimaryOrderHeader header(RDP::STANDARD, 0);

        if (!common.clip.contains(this->el.get_rect())){
            header.control |= RDP::BOUNDS;
        }

        const int16_t oldleft   = oldcmd.el.left();
        const int16_t oldtop    = oldcmd.el.top();
        const int16_t oldright  = oldcmd.el.right();
        const int16_t oldbottom = oldcmd.el.bottom();

        header.control |= (is_1_byte(this->el.left() - oldleft) &&
                           is_1_byte(this->el.top() - oldtop) &&
                           is_1_byte(this->el.right() - oldright) &&
                           is_1_byte(this->el.bottom() - oldbottom)) * RDP::DELTA;

        header.fields =
            ( this->el.left()   != oldleft        ) * 0x0001
            |(this->el.top()    != oldtop         ) * 0x0002
            |(this->el.right()  != oldright       ) * 0x0004
            |(this->el.bottom() != oldbottom      ) * 0x0008
            |(this->bRop2    != oldcmd.bRop2   ) * 0x0010
            |(this->fillMode != oldcmd.fillMode) * 0x0020
            |(this->color    != oldcmd.color   ) * 0x0040;

        common.emit(stream, header, oldcommon);
        header.emit_coord(stream, 0x0001, this->el.left(),   oldleft);
        header.emit_coord(stream, 0x0002, this->el.top(),    oldtop);
        header.emit_coord(stream, 0x0004, this->el.right(),  oldright);
        header.emit_coord(stream, 0x0008, this->el.bottom(), oldbottom);

        if (header.fields & 0x0010) { stream.out_uint8(this->bRop2); }

        if (header.fields & 0x0020) { stream.out_uint8(this->fillMode); }

        if (header.fields & 0x0040) {
            emit_rdp_color(stream, this->color);
        }

        // LOG(LOG_INFO, "RDPEllipseSC::emit: header fields=0x%02X", header.fields);
        // LOG(LOG_INFO, "RDPEllipseSC::emit: header color=0x%02X", this->color);
    }
 size_t str(char * buffer, size_t sz, const RDPOrderCommon & common) const {
     size_t lg = 0;
     lg += common.str(buffer + lg, sz - lg, true);
     lg += snprintf(buffer + lg, sz - lg,
         "MultiDstBlt(nLeftRect=%d nTopRect=%d nWidth=%d nHeight=%d bRop=0x%02X nDeltaEntries=%d "
             "CodedDeltaList=(",
         this->nLeftRect, this->nTopRect, this->nWidth, this->nHeight, this->bRop, this->nDeltaEntries);
     for (uint8_t i = 0; i < this->nDeltaEntries; i++) {
         if (i) {
             lg += snprintf(buffer + lg, sz - lg, " ");
         }
         lg += snprintf(buffer + lg, sz - lg, "(%d, %d, %d, %d)", this->deltaEncodedRectangles[i].leftDelta,
             this->deltaEncodedRectangles[i].topDelta, this->deltaEncodedRectangles[i].width,
             this->deltaEncodedRectangles[i].height);
     }
     lg += snprintf(buffer + lg, sz - lg, "))");
     if (lg >= sz) {
         return sz;
     }
     return lg;
 }
    void emit(OutStream & stream, RDPOrderCommon & common, const RDPOrderCommon & oldcommon,
              const RDPPolygonCB & oldcmd) const {
        RDPPrimaryOrderHeader header(RDP::STANDARD, 0);

        // TODO check that
        int16_t pointx = this->xStart;
        int16_t pointy = this->yStart;
        if (!common.clip.contains_pt(pointx, pointy)) {
            header.control |= RDP::BOUNDS;
        }
        else {
            for (uint8_t i = 0; i < this->NumDeltaEntries; i++) {
                pointx += this->deltaPoints[i].xDelta;
                pointy += this->deltaPoints[i].yDelta;

                if (!common.clip.contains_pt(pointx, pointy)) {
                    header.control |= RDP::BOUNDS;
                    break;
                }
            }
        }

        header.control |= (is_1_byte(this->xStart - oldcmd.xStart) && is_1_byte(this->yStart - oldcmd.yStart)) * RDP::DELTA;

        header.fields =
              (this->xStart          != oldcmd.xStart         ) * 0x0001
            | (this->yStart          != oldcmd.yStart         ) * 0x0002
            | (this->bRop2           != oldcmd.bRop2          ) * 0x0004
            | (this->fillMode        != oldcmd.fillMode       ) * 0x0008
            | (this->backColor       != oldcmd.backColor      ) * 0x0010
            | (this->foreColor       != oldcmd.foreColor      ) * 0x0020
            | (this->brush.org_x     != oldcmd.brush.org_x    ) * 0x0040
            | (this->brush.org_y     != oldcmd.brush.org_y    ) * 0x0080
            | (this->brush.style     != oldcmd.brush.style    ) * 0x0100
            | (this->brush.hatch     != oldcmd.brush.hatch    ) * 0x0200
            | (memcmp(this->brush.extra, oldcmd.brush.extra, 7) != 0) * 0x0400
            | (this->NumDeltaEntries != oldcmd.NumDeltaEntries) * 0x0800
            | ((this->NumDeltaEntries != oldcmd.NumDeltaEntries) ||
               memcmp(this->deltaPoints, oldcmd.deltaPoints,
                      this->NumDeltaEntries * sizeof(DeltaPoint))
               ) * 0x1000
              ;

        common.emit(stream, header, oldcommon);

        header.emit_coord(stream, 0x0001, this->xStart, oldcmd.xStart);
        header.emit_coord(stream, 0x0002, this->yStart, oldcmd.yStart);

        if (header.fields & 0x0004) { stream.out_uint8(this->bRop2); }

        if (header.fields & 0x0008) { stream.out_uint8(this->fillMode); }

        if (header.fields & 0x0010) {
            emit_rdp_color(stream, this->backColor);
        }
        if (header.fields & 0x0020) {
            emit_rdp_color(stream, this->foreColor);
        }

        header.emit_brush(stream, 0x0040, this->brush, oldcmd.brush);

        if (header.fields & 0x0800) { stream.out_uint8(this->NumDeltaEntries); }

        if (header.fields & 0x1000) {
            uint32_t offset_cbData = stream.get_offset();
            stream.out_clear_bytes(1);

            uint8_t * zeroBit = stream.get_current();
            stream.out_clear_bytes((this->NumDeltaEntries + 3) / 4);
            *zeroBit = 0;

            for (uint8_t i = 0, m4 = 0; i < this->NumDeltaEntries; i++, m4++) {
                if (m4 == 4) {
                    m4 = 0;
                }

                if (i && !m4) {
                    *(++zeroBit) = 0;
                }

                if (!this->deltaPoints[i].xDelta) {
                    *zeroBit |= (1 << (7 - m4 * 2));
                }
                else {
                    stream.out_DEP(this->deltaPoints[i].xDelta);
                }

                if (!this->deltaPoints[i].yDelta) {
                    *zeroBit |= (1 << (6 - m4 * 2));
                }
                else {
                    stream.out_DEP(this->deltaPoints[i].yDelta);
                }
            }

            stream.set_out_uint8(stream.get_offset() - offset_cbData - 1, offset_cbData);
        }
    }
Exemple #12
0
    void emit( OutStream & stream, RDPOrderCommon & common, const RDPOrderCommon & oldcommon
             , const RDPMultiDstBlt & oldcmd) const {
        RDPPrimaryOrderHeader header(RDP::STANDARD, 0);

        int16_t nLeftRect = 0;
        int16_t nTopRect  = 0;
        int16_t nWidth    = 0;
        int16_t nHeight   = 0;
        if (!common.clip.contains(Rect(nLeftRect, nTopRect, nWidth, nHeight))) {
            header.control |= RDP::BOUNDS;
        }
        else {
            for (uint8_t i = 0; i < this->nDeltaEntries; i++) {
                nLeftRect += this->deltaEncodedRectangles[i].leftDelta;
                nTopRect  += this->deltaEncodedRectangles[i].topDelta;
                nWidth    =  this->deltaEncodedRectangles[i].width;
                nHeight   =  this->deltaEncodedRectangles[i].height;

                if (!common.clip.contains(Rect(nLeftRect, nTopRect, nWidth, nHeight))) {
                    header.control |= RDP::BOUNDS;
                    break;
                }
            }
        }

        header.control |= (is_1_byte(this->nLeftRect - oldcmd.nLeftRect) && is_1_byte(this->nTopRect - oldcmd.nTopRect) &&
            is_1_byte(this->nWidth - oldcmd.nWidth) && is_1_byte(this->nHeight - oldcmd.nHeight)) * RDP::DELTA;

        header.fields =
                (this->nLeftRect     != oldcmd.nLeftRect    ) * 0x0001
              | (this->nTopRect      != oldcmd.nTopRect     ) * 0x0002
              | (this->nWidth        != oldcmd.nWidth       ) * 0x0004
              | (this->nHeight       != oldcmd.nHeight      ) * 0x0008
              | (this->bRop          != oldcmd.bRop         ) * 0x0010
              | (this->nDeltaEntries != oldcmd.nDeltaEntries) * 0x0020
              | (
                 (this->nDeltaEntries != oldcmd.nDeltaEntries) ||
                 memcmp(this->deltaEncodedRectangles, oldcmd.deltaEncodedRectangles,
                        this->nDeltaEntries * sizeof(RDP::DeltaEncodedRectangle))
                                                            ) * 0x0040
              ;

        common.emit(stream, header, oldcommon);

        header.emit_coord(stream, 0x0001, this->nLeftRect, oldcmd.nLeftRect);
        header.emit_coord(stream, 0x0002, this->nTopRect,  oldcmd.nTopRect);
        header.emit_coord(stream, 0x0004, this->nWidth,    oldcmd.nWidth);
        header.emit_coord(stream, 0x0008, this->nHeight,   oldcmd.nHeight);

        if (header.fields & 0x0010) { stream.out_uint8(this->bRop); }

        if (header.fields & 0x0020) { stream.out_uint8(this->nDeltaEntries); }

        if (header.fields & 0x0040) {
            uint32_t offset_cbData = stream.get_offset();
            stream.out_clear_bytes(2);


            uint8_t * zeroBit = stream.get_current();
            stream.out_clear_bytes((this->nDeltaEntries + 1) / 2);

            *zeroBit = 0;
            for (uint8_t i = 0, m2 = 0; i < this->nDeltaEntries; i++, m2++) {
                if (m2 == 2) {
                    m2 = 0;
                }

                if (i && !m2) {
                    *(++zeroBit) = 0;
                }

                if (!this->deltaEncodedRectangles[i].leftDelta) {
                    *zeroBit |= (1 << (7 - m2 * 4));
                }
                else {
                    stream.out_DEP(this->deltaEncodedRectangles[i].leftDelta);
                }

                if (!this->deltaEncodedRectangles[i].topDelta) {
                    *zeroBit |= (1 << (6 - m2 * 4));
                }
                else {
                    stream.out_DEP(this->deltaEncodedRectangles[i].topDelta);
                }

                if (!this->deltaEncodedRectangles[i].width) {
                    *zeroBit |= (1 << (5 - m2 * 4));
                }
                else {
                    stream.out_DEP(this->deltaEncodedRectangles[i].width);
                }

                if (!this->deltaEncodedRectangles[i].height) {
                    *zeroBit |= (1 << (4 - m2 * 4));
                }
                else {
                    stream.out_DEP(this->deltaEncodedRectangles[i].height);
                }
            }

            stream.set_out_uint16_le(stream.get_offset() - offset_cbData - 2, offset_cbData);
        }
    }   // void emit(OutStream & stream, RDPOrderCommon & common, const RDPOrderCommon & oldcommon, const RDPMultiDstBlt & oldcmd) const
    // order to stream returns true if state clip must be changed
    // it does not change state by itself
    void emit(OutStream & stream,
                RDPOrderCommon & common,
                const RDPOrderCommon & oldcommon,
                const RDPOpaqueRect & oldcmd) const
    {
        using namespace RDP;
        RDPPrimaryOrderHeader header(STANDARD, 0);

        if (!common.clip.contains(this->rect)){
            header.control |= BOUNDS;
        }

        // OPAQUERECT fields bytes (1 byte)
        // ------------------------------
        // 0x01: x coordinate
        // 0x02: y coordinate
        // 0x04: cx coordinate
        // 0x08: cy coordinate
        // 0x10: red color byte
        // 0x20: green color byte
        // 0x40: blue color byte

        // Note by CGR:
        // ------------
        // As far as we can see the OPAQUERECT fields called "red" "green" and
        // "blue" don't care much for actual color components. Really they
        // should be called "first color byte", "second color byte" and "third
        // color byte". They are red green and blue only in 24 bits. In 15 or 16
        // one byte is always empty and changing green component will
        // change both used bytes.

        DeltaRect dr(this->rect, oldcmd.rect);

        // RDP specs says that we can have DELTA only if we
        // have bounds. Can't see the rationale and rdesktop don't do it
        // by the book. Behavior should be checked with server and clients
        // from Microsoft. Looks like an error in RDP specs.
        header.control |= dr.fully_relative() * DELTA;

        uint32_t diff_color = this->color ^ oldcmd.color;

//        LOG(LOG_INFO, "emit opaque rect old_color = %.6x new_color = %.6x\n", oldcmd.color, this->color);

        header.fields =   (dr.dleft                != 0) * 0x01
                        | (dr.dtop                 != 0) * 0x02
                        | (dr.dwidth               != 0) * 0x04
                        | (dr.dheight              != 0) * 0x08
                        | ((diff_color & 0x0000FF) != 0) * 0x10
                        | ((diff_color & 0x00FF00) != 0) * 0x20
                        | ((diff_color & 0xFF0000) != 0) * 0x40
                        ;

        common.emit(stream, header, oldcommon);
        header.emit_rect(stream, 0x01, this->rect, oldcmd.rect);

        if (header.fields & 0x10){
            stream.out_uint8(this->color);
        }
        if (header.fields & 0x20){
            stream.out_uint8(this->color >> 8);
        }