Example #1
0
pixman_image_t *alloc_lz_image_surface(LzDecodeUsrData *canvas_data,
                                       pixman_format_code_t pixman_format, int width,
                                       int height, int gross_pixels, int top_down)
{
    int stride;
    pixman_image_t *surface = NULL;

    stride = (gross_pixels / height) * (PIXMAN_FORMAT_BPP (pixman_format) / 8);

    /* pixman requires strides to be 4-byte aligned */
    stride = SPICE_ALIGN(stride, 4);
    
    if (!top_down) {
        stride = -stride;
    }

   surface = surface_create_stride(
#ifdef WIN32
            canvas_data->dc,
#endif
            pixman_format, width, height, stride);
    canvas_data->out_surface = surface;
    return surface;
}
Example #2
0
static Pixmap *init_bitmap(size_t input_size, uint8_t *buf)
{
    BMPFileHeader *file_header;
    uint8_t *pixels;
    Pixmap *pixmap;
    uint32_t stride;


    if (input_size < sizeof(BMPFileHeader)) {
        ERROR("invalid source file");
        return NULL;
    }

    file_header = (BMPFileHeader *)buf;

    if (file_header->magic != 0x4d42) {
        ERROR("bad bitmap magic");
        return NULL;
    }

    if (file_header->file_size != input_size) {
        ERROR("invalid source file");
        return NULL;
    }

    if (file_header->header.header_size != 40 || file_header->header.plans != 1 ||
                                                        file_header->header.compression != BI_RGB ||
                                                        !file_header->header.width ||
                                                        !file_header->header.height) {
        ERROR("invalid bitmap header");
        return NULL;
    }

    if (file_header->header.bpp == 32) {
        stride = file_header->header.width * sizeof(uint32_t);
    } else if (file_header->header.bpp == 24) {
        stride = SPICE_ALIGN(file_header->header.width * 3, 4);
    } else {
        ERROR("unsupported bpp");
        return NULL;
    }

    if (file_header->header.height * stride > file_header->header.image_size) {
        ERROR("image size is to small");
        return NULL;
    }
    pixels = buf + file_header->data_offset;
    if (pixels < (uint8_t *)(file_header + 1) ||
                                       pixels + file_header->header.image_size > buf + input_size) {
        ERROR("bad data offset");
        return NULL;
    }

    if (!(pixmap = (Pixmap *)malloc(sizeof(*pixmap)))) {
        ERROR("alloc mem failed");
        return NULL;
    }

    pixmap->width = file_header->header.width;
    pixmap->height = file_header->header.height;
    pixmap->stride = stride;
    pixmap->bpp = file_header->header.bpp;
    pixmap->data = pixels;
    return pixmap;
}
Example #3
0
pixman_image_t * surface_create(pixman_format_code_t format, int width, int height, int top_down)
#endif
{
#ifdef WIN32
    /*
     * Windows xp allow only 10,000 of gdi handlers, considering the fact that
     * we limit here the number to 5000, we dont use atomic operations to sync
     * this calculation against the other canvases (in case of multiple
     * monitors), in worst case there will be little more than 5000 gdi
     * handlers.
     */
    if (dc && gdi_handlers < 5000) {
        uint8_t *data;
        uint8_t *src;
        struct {
            BITMAPINFO inf;
            RGBQUAD palette[255];
        } bitmap_info;
        int nstride;
        pixman_image_t *surface;
        PixmanData *pixman_data;
        HBITMAP bitmap;
        HANDLE mutex;

        memset(&bitmap_info, 0, sizeof(bitmap_info));
        bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader);
        bitmap_info.inf.bmiHeader.biWidth = width;

        bitmap_info.inf.bmiHeader.biHeight = (!top_down) ? height : -height;

        bitmap_info.inf.bmiHeader.biPlanes = 1;
        switch (format) {
        case PIXMAN_a8r8g8b8:
        case PIXMAN_x8r8g8b8:
            bitmap_info.inf.bmiHeader.biBitCount = 32;
            nstride = width * 4;
            break;
        case PIXMAN_x1r5g5b5:
        case PIXMAN_r5g6b5:
            bitmap_info.inf.bmiHeader.biBitCount = 16;
            nstride = SPICE_ALIGN(width * 2, 4);
            break;
        case PIXMAN_a8:
            bitmap_info.inf.bmiHeader.biBitCount = 8;
            nstride = SPICE_ALIGN(width, 4);
            break;
        case PIXMAN_a1:
            bitmap_info.inf.bmiHeader.biBitCount = 1;
            nstride = SPICE_ALIGN(width, 32) / 8;
            break;
        default:
            spice_error("invalid format");
            return NULL;
        }

        bitmap_info.inf.bmiHeader.biCompression = BI_RGB;

        mutex = CreateMutex(NULL, 0, NULL);
        if (!mutex) {
            spice_error("Unable to CreateMutex");
        }

        bitmap = CreateDIBSection(dc, &bitmap_info.inf, 0, (VOID **)&data, NULL, 0);
        if (!bitmap) {
            CloseHandle(mutex);
            spice_error("Unable to CreateDIBSection");
        }

        if (top_down) {
            src = data;
        } else {
            src = data + nstride * (height - 1);
            nstride = -nstride;
        }

        surface = pixman_image_create_bits(format, width, height, (uint32_t *)src, nstride);
        if (surface == NULL) {
            CloseHandle(mutex);
            DeleteObject(bitmap);
            spice_error("create surface failed, out of memory");
        }
        pixman_data = pixman_image_add_data(surface);
        pixman_data->format = format;
        pixman_data->bitmap = bitmap;
        pixman_data->mutex = mutex;
        gdi_handlers++;
        return surface;
    } else {
#endif
    if (top_down) {
        pixman_image_t *surface;
        PixmanData *data;

        surface = pixman_image_create_bits(format, width, height, NULL, 0);
        data = pixman_image_add_data(surface);
        data->format = format;
        return surface;
    } else {
        // NOTE: we assume here that the lz decoders always decode to RGB32.
        int stride = 0;
        switch (format) {
        case PIXMAN_a8r8g8b8:
        case PIXMAN_x8r8g8b8:
            stride = width * 4;
            break;
        case PIXMAN_x1r5g5b5:
        case PIXMAN_r5g6b5:
            stride = SPICE_ALIGN(width * 2, 4);
            break;
        case PIXMAN_a8:
            stride = SPICE_ALIGN(width, 4);
            break;
        case PIXMAN_a1:
            stride = SPICE_ALIGN(width, 32) / 8;
            break;
        default:
            spice_error("invalid format");
        }
        stride = -stride;
        return __surface_create_stride(format, width, height, stride);
    }
#ifdef WIN32
}

#endif
}
static uint8_t * parse_msgc_tunnel_service_add(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    size_t mem_size, nw_size;
    uint8_t *in, *end;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    size_t name__extra_size;
    size_t description__extra_size;
    size_t u__nw_size;
    uint16_t type__value;
    SpiceMsgcTunnelAddGenericService *out;
    uint32_t i;

    { /* name */
        uint32_t name__value;
        uint32_t name__array__nw_size;
        uint32_t name__array__mem_size;
        pos = (start + 14);
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        name__value = read_uint32(pos);
        if (SPICE_UNLIKELY(message_start + name__value >= message_end)) {
            goto error;
        }
        name__array__nw_size = spice_strnlen((char *)message_start + name__value, message_end - (message_start + name__value));
        if (SPICE_UNLIKELY(*(message_start + name__value + name__array__nw_size) != 0)) {
            goto error;
        }
        name__array__mem_size = name__array__nw_size;
        /* @nocopy, so no extra size */
        name__extra_size = 0;
    }

    { /* description */
        uint32_t description__value;
        uint32_t description__array__nw_size;
        uint32_t description__array__mem_size;
        pos = (start + 18);
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        description__value = read_uint32(pos);
        if (SPICE_UNLIKELY(message_start + description__value >= message_end)) {
            goto error;
        }
        description__array__nw_size = spice_strnlen((char *)message_start + description__value, message_end - (message_start + description__value));
        if (SPICE_UNLIKELY(*(message_start + description__value + description__array__nw_size) != 0)) {
            goto error;
        }
        description__array__mem_size = description__array__nw_size;
        /* @nocopy, so no extra size */
        description__extra_size = 0;
    }

    { /* u */
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 2 > message_end)) {
            goto error;
        }
        type__value = read_uint16(pos);
        if (type__value == SPICE_TUNNEL_SERVICE_TYPE_IPP) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 22);
            size_t u__nw_size;
            uint16_t type__value;
            { /* u */
                uint32_t u__nelements;
                pos = start2 + 0;
                if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                    goto error;
                }
                type__value = read_uint16(pos);
                if (type__value == SPICE_TUNNEL_IP_TYPE_IPv4) {
                    u__nelements = 4;

                    u__nw_size = u__nelements;
                } else {
                    u__nw_size = 0;
                }

            }

            u__nw_size = 2 + u__nw_size;
        } else {
            u__nw_size = 0;
        }

    }

    nw_size = 22 + u__nw_size;
    mem_size = sizeof(SpiceMsgcTunnelAddGenericService) + name__extra_size + description__extra_size;

    /* Check if message fits in reported side */
    if (start + nw_size > message_end) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)malloc(mem_size);
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcTunnelAddGenericService);
    in = start;

    out = (SpiceMsgcTunnelAddGenericService *)data;

    out->type = consume_uint16(&in);
    out->id = consume_uint32(&in);
    out->group = consume_uint32(&in);
    out->port = consume_uint32(&in);
    /* Reuse data from network message */
    out->name = (size_t)(message_start + consume_uint32(&in));
    /* Reuse data from network message */
    out->description = (size_t)(message_start + consume_uint32(&in));
    if (out->type == SPICE_TUNNEL_SERVICE_TYPE_IPP) {
        out->u.ip.type = consume_uint16(&in);
        if (out->u.ip.type == SPICE_TUNNEL_IP_TYPE_IPv4) {
            uint32_t ipv4__nelements;
            ipv4__nelements = 4;
            memcpy(out->u.ip.u.ipv4, in, ipv4__nelements);
            in += ipv4__nelements;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((size_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    if (data != NULL) {
        free(data);
    }
    return NULL;
}