Merge branch 'master' of github.com:neutrinolabs/xrdp
This commit is contained in:
commit
06f01f6c37
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2012
|
||||
* Copyright (C) Jay Sorg 2004-2013
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -125,6 +125,7 @@ int APP_CC g_get_errno(void);
|
||||
int APP_CC g_execvp(const char* p1, char* args[]);
|
||||
int APP_CC g_execlp3(const char* a1, const char* a2, const char* a3);
|
||||
void APP_CC g_signal_child_stop(void (*func)(int));
|
||||
void APP_CC g_signal_segfault(void (*func)(int));
|
||||
void APP_CC g_signal_hang_up(void (*func)(int));
|
||||
void APP_CC g_signal_user_interrupt(void (*func)(int));
|
||||
void APP_CC g_signal_kill(void (*func)(int));
|
||||
|
@ -55,6 +55,9 @@ struct stream
|
||||
/******************************************************************************/
|
||||
#define s_check_rem(s, n) ((s)->p + (n) <= (s)->end)
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check_rem_out(s, n) ((s)->p + (n) <= (s)->data + (s)->size)
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check_end(s) ((s)->p == (s)->end)
|
||||
|
||||
|
135
common/trans.c
135
common/trans.c
@ -90,6 +90,86 @@ trans_get_wait_objs(struct trans *self, tbus *objs, int *count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
trans_get_wait_objs_rw(struct trans *self,
|
||||
tbus *robjs, int *rcount,
|
||||
tbus *wobjs, int *wcount)
|
||||
{
|
||||
if (self == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (self->status != TRANS_STATUS_UP)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
robjs[*rcount] = self->sck;
|
||||
(*rcount)++;
|
||||
|
||||
if (self->wait_s != 0)
|
||||
{
|
||||
wobjs[*wcount] = self->sck;
|
||||
(*wcount)++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
send_waiting(struct trans *self, int block)
|
||||
{
|
||||
struct stream *temp_s;
|
||||
int bytes;
|
||||
int sent;
|
||||
int timeout;
|
||||
int cont;
|
||||
|
||||
timeout = block ? 100 : 0;
|
||||
cont = 1;
|
||||
while (cont)
|
||||
{
|
||||
if (self->wait_s != 0)
|
||||
{
|
||||
temp_s = self->wait_s;
|
||||
if (g_tcp_can_send(self->sck, timeout))
|
||||
{
|
||||
bytes = (int) (temp_s->end - temp_s->p);
|
||||
sent = g_tcp_send(self->sck, temp_s->p, bytes, 0);
|
||||
if (sent > 0)
|
||||
{
|
||||
temp_s->p += sent;
|
||||
if (temp_s->p >= temp_s->end)
|
||||
{
|
||||
self->wait_s = (struct stream *) (temp_s->next_packet);
|
||||
free_stream(temp_s);
|
||||
}
|
||||
}
|
||||
else if (sent == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!g_tcp_last_error_would_block(self->sck))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
cont = block;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
trans_check_wait_objs(struct trans *self)
|
||||
@ -203,6 +283,12 @@ trans_check_wait_objs(struct trans *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (send_waiting(self, 0) != 0)
|
||||
{
|
||||
/* error */
|
||||
self->status = TRANS_STATUS_DOWN;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -221,8 +307,12 @@ trans_force_read_s(struct trans *self, struct stream *in_s, int size)
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
/* make sure stream has room */
|
||||
if ((in_s->end + size) > (in_s->data + in_s->size))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
rcvd = g_tcp_recv(self->sck, in_s->end, size, 0);
|
||||
|
||||
if (rcvd == -1)
|
||||
{
|
||||
if (g_tcp_last_error_would_block(self->sck))
|
||||
@ -287,6 +377,12 @@ trans_force_write_s(struct trans *self, struct stream *out_s)
|
||||
size = (int)(out_s->end - out_s->data);
|
||||
total = 0;
|
||||
|
||||
if (send_waiting(self, 1) != 0)
|
||||
{
|
||||
self->status = TRANS_STATUS_DOWN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (total < size)
|
||||
{
|
||||
sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0);
|
||||
@ -338,6 +434,43 @@ trans_force_write(struct trans *self)
|
||||
return trans_force_write_s(self, self->out_s);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
trans_write_copy(struct trans *self)
|
||||
{
|
||||
int size;
|
||||
struct stream *out_s;
|
||||
struct stream *wait_s;
|
||||
struct stream *temp_s;
|
||||
|
||||
if (self->status != TRANS_STATUS_UP)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_s = self->out_s;
|
||||
size = (int)(out_s->end - out_s->data);
|
||||
make_stream(wait_s);
|
||||
init_stream(wait_s, size);
|
||||
out_uint8a(wait_s, out_s->data, size);
|
||||
s_mark_end(wait_s);
|
||||
wait_s->p = wait_s->data;
|
||||
if (self->wait_s == 0)
|
||||
{
|
||||
self->wait_s = wait_s;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_s = self->wait_s;
|
||||
while (temp_s->next_packet != 0)
|
||||
{
|
||||
temp_s = (struct stream *) (temp_s->next_packet);
|
||||
}
|
||||
temp_s->next_packet = wait_s;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
trans_connect(struct trans *self, const char *server, const char *port,
|
||||
|
@ -54,6 +54,7 @@ struct trans
|
||||
struct stream* out_s;
|
||||
char* listen_filename;
|
||||
tis_term is_term; /* used to test for exit */
|
||||
struct stream* wait_s;
|
||||
};
|
||||
|
||||
struct trans* APP_CC
|
||||
@ -73,6 +74,8 @@ trans_force_read(struct trans* self, int size);
|
||||
int APP_CC
|
||||
trans_force_write(struct trans* self);
|
||||
int APP_CC
|
||||
trans_write_copy(struct trans* self);
|
||||
int APP_CC
|
||||
trans_connect(struct trans* self, const char* server, const char* port,
|
||||
int timeout);
|
||||
int APP_CC
|
||||
|
@ -559,4 +559,7 @@
|
||||
#define CMDTYPE_FRAME_MARKER 0x0004
|
||||
#define CMDTYPE_STREAM_SURFACE_BITS 0x0006
|
||||
|
||||
#define XRDP_MAX_BITMAP_CACHE_ID 3
|
||||
#define XRDP_MAX_BITMAP_CACHE_IDX 2000
|
||||
|
||||
#endif
|
||||
|
@ -39,6 +39,10 @@ AC_ARG_ENABLE(jpeg, AS_HELP_STRING([--enable-jpeg],
|
||||
[Build jpeg module (default: no)]),
|
||||
[jpeg=true], [jpeg=false])
|
||||
AM_CONDITIONAL(XRDP_JPEG, [test x$jpeg = xtrue])
|
||||
AC_ARG_ENABLE(tjpeg, AS_HELP_STRING([--enable-tjpeg],
|
||||
[Build turbo jpeg module(assumes /opt/libjpeg-turbo) (default: no)]),
|
||||
[tjpeg=true], [tjpeg=false])
|
||||
AM_CONDITIONAL(XRDP_TJPEG, [test x$tjpeg = xtrue])
|
||||
AC_ARG_ENABLE(simplesound, AS_HELP_STRING([--enable-simplesound],
|
||||
[Build simple pulse audio interface (default: no)]),
|
||||
[simplesound=true], [simplesound=false])
|
||||
|
@ -16,10 +16,17 @@ EXTRA_DEFINES += -DXRDP_NEUTRINORDP
|
||||
EXTRA_LIBS += $(FREERDP_LIBS)
|
||||
endif
|
||||
|
||||
if XRDP_TJPEG
|
||||
EXTRA_DEFINES += -DXRDP_JPEG -DXRDP_TJPEG
|
||||
EXTRA_INCLUDES += -I/opt/libjpeg-turbo/include
|
||||
EXTRA_FLAGS += -L/opt/libjpeg-turbo/lib -Wl,-rpath -Wl,/opt/libjpeg-turbo/lib
|
||||
EXTRA_LIBS += -lturbojpeg
|
||||
else
|
||||
if XRDP_JPEG
|
||||
EXTRA_DEFINES += -DXRDP_JPEG
|
||||
EXTRA_LIBS += -ljpeg
|
||||
endif
|
||||
endif
|
||||
|
||||
if GOT_PREFIX
|
||||
EXTRA_INCLUDES += -I$(prefix)/include
|
||||
|
@ -211,6 +211,7 @@ struct xrdp_orders
|
||||
int order_count;
|
||||
int order_level; /* inc for every call to xrdp_orders_init */
|
||||
struct xrdp_orders_state orders_state;
|
||||
void* jpeg_han;
|
||||
};
|
||||
|
||||
#define PROTO_RDP_40 1
|
||||
@ -431,10 +432,14 @@ xrdp_bitmap_compress(char* in_data, int width, int height,
|
||||
int start_line, struct stream* temp_s,
|
||||
int e);
|
||||
int APP_CC
|
||||
xrdp_jpeg_compress(char* in_data, int width, int height,
|
||||
xrdp_jpeg_compress(void *handle, char* in_data, int width, int height,
|
||||
struct stream* s, int bpp, int byte_limit,
|
||||
int start_line, struct stream* temp_s,
|
||||
int e, int quality);
|
||||
void *APP_CC
|
||||
xrdp_jpeg_init(void);
|
||||
int APP_CC
|
||||
xrdp_jpeg_deinit(void *handle);
|
||||
|
||||
/* xrdp_channel.c */
|
||||
struct xrdp_channel* APP_CC
|
||||
|
@ -72,20 +72,38 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code)
|
||||
in_uint8s(s, 1);
|
||||
in_uint16_be(s, len);
|
||||
|
||||
if (len < 4)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (xrdp_tcp_recv(self->tcp_layer, s, len - 4) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 1);
|
||||
in_uint8(s, *code);
|
||||
|
||||
if (*code == ISO_PDU_DT)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, 5))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 5);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,112 @@
|
||||
|
||||
#include "libxrdp.h"
|
||||
|
||||
#if defined(XRDP_JPEG)
|
||||
#if defined(XRDP_TJPEG)
|
||||
|
||||
/* turbo jpeg */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <turbojpeg.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_jpeg_compress(void *handle, char *in_data, int width, int height,
|
||||
struct stream *s, int bpp, int byte_limit,
|
||||
int start_line, struct stream *temp_s,
|
||||
int e, int quality)
|
||||
{
|
||||
int error;
|
||||
int i;
|
||||
int j;
|
||||
unsigned int pixel;
|
||||
unsigned int *src32;
|
||||
unsigned int *dst32;
|
||||
unsigned long cdata_bytes;
|
||||
unsigned char *src_buf;
|
||||
unsigned char *dst_buf;
|
||||
char *temp_buf;
|
||||
tjhandle tj_han;
|
||||
|
||||
if (bpp != 24)
|
||||
{
|
||||
g_writeln("xrdp_jpeg_compress: bpp wrong %d", bpp);
|
||||
return height;
|
||||
}
|
||||
if (handle == 0)
|
||||
{
|
||||
g_writeln("xrdp_jpeg_compress: handle is nil");
|
||||
return height;
|
||||
}
|
||||
tj_han = (tjhandle) handle;
|
||||
cdata_bytes = byte_limit;
|
||||
src_buf = (unsigned char *) in_data;
|
||||
dst_buf = (unsigned char *) (s->p);
|
||||
temp_buf = 0;
|
||||
if (e == 0)
|
||||
{
|
||||
src_buf = (unsigned char*)in_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_buf = (char *) g_malloc((width + e) * height * 4, 0);
|
||||
dst32 = (unsigned int *) temp_buf;
|
||||
src32 = (unsigned int *) in_data;
|
||||
for (j = 0; j < height; j++)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
pixel = *src32;
|
||||
src32++;
|
||||
*dst32 = pixel;
|
||||
dst32++;
|
||||
}
|
||||
for (i = 0; i < e; i++)
|
||||
{
|
||||
*dst32 = pixel;
|
||||
dst32++;
|
||||
}
|
||||
}
|
||||
src_buf = (unsigned char *) temp_buf;
|
||||
}
|
||||
dst_buf = (unsigned char*)(s->p);
|
||||
error = tjCompress(tj_han, src_buf, width + e, (width + e) * 4, height,
|
||||
TJPF_XBGR, dst_buf, &cdata_bytes,
|
||||
TJSAMP_420, quality, 0);
|
||||
s->p += cdata_bytes;
|
||||
g_free(temp_buf);
|
||||
return height;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void *APP_CC
|
||||
xrdp_jpeg_init(void)
|
||||
{
|
||||
tjhandle tj_han;
|
||||
|
||||
tj_han = tjInitCompress();
|
||||
return tj_han;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_jpeg_deinit(void *handle)
|
||||
{
|
||||
tjhandle tj_han;
|
||||
|
||||
if (handle == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
tj_han = (tjhandle) handle;
|
||||
tjDestroy(tj_han);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(XRDP_JPEG)
|
||||
|
||||
/* libjpeg */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -205,7 +310,7 @@ jpeg_compress(char *in_data, int width, int height,
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_jpeg_compress(char *in_data, int width, int height,
|
||||
xrdp_jpeg_compress(void *handle, char *in_data, int width, int height,
|
||||
struct stream *s, int bpp, int byte_limit,
|
||||
int start_line, struct stream *temp_s,
|
||||
int e, int quality)
|
||||
@ -215,11 +320,25 @@ xrdp_jpeg_compress(char *in_data, int width, int height,
|
||||
return height;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void *APP_CC
|
||||
xrdp_jpeg_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_jpeg_deinit(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_jpeg_compress(char *in_data, int width, int height,
|
||||
xrdp_jpeg_compress(void *handle, char *in_data, int width, int height,
|
||||
struct stream *s, int bpp, int byte_limit,
|
||||
int start_line, struct stream *temp_s,
|
||||
int e, int quality)
|
||||
@ -227,4 +346,18 @@ xrdp_jpeg_compress(char *in_data, int width, int height,
|
||||
return height;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void *APP_CC
|
||||
xrdp_jpeg_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_jpeg_deinit(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -132,6 +132,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, opcode);
|
||||
appid = opcode >> 2;
|
||||
|
||||
@ -145,6 +150,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
|
||||
/* this is channels getting added from the client */
|
||||
if (appid == MCS_CJRQ)
|
||||
{
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint16_be(s, userid);
|
||||
in_uint16_be(s, chanid);
|
||||
log_message(LOG_LEVEL_DEBUG,"MCS_CJRQ - channel join request received");
|
||||
@ -176,6 +186,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 6))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 2);
|
||||
in_uint16_be(s, *chan);
|
||||
in_uint8s(s, 1);
|
||||
@ -183,6 +198,10 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
|
||||
|
||||
if (len & 0x80)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 1);
|
||||
}
|
||||
|
||||
@ -202,10 +221,18 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
|
||||
|
||||
if (tag_val > 0xff)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_be(s, tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, tag);
|
||||
}
|
||||
|
||||
@ -214,6 +241,11 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, l);
|
||||
|
||||
if (l & 0x80)
|
||||
@ -223,6 +255,10 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
|
||||
|
||||
while (l > 0)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, i);
|
||||
*len = (*len << 8) | i;
|
||||
l--;
|
||||
@ -255,6 +291,11 @@ xrdp_mcs_parse_domain_params(struct xrdp_mcs *self, struct stream *s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((len < 0) || !s_check_rem(s, len))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, len);
|
||||
|
||||
if (s_check(s))
|
||||
@ -276,7 +317,7 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
|
||||
struct stream *s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
init_stream(s, 16 * 1024);
|
||||
|
||||
if (xrdp_iso_recv(self->iso_layer, s) != 0)
|
||||
{
|
||||
@ -296,6 +337,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((len < 0) || !s_check_rem(s, len))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, len);
|
||||
|
||||
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
|
||||
@ -304,6 +351,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((len < 0) || !s_check_rem(s, len))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, len);
|
||||
|
||||
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0)
|
||||
@ -312,6 +365,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((len < 0) || !s_check_rem(s, len))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, len);
|
||||
|
||||
if (xrdp_mcs_parse_domain_params(self, s) != 0)
|
||||
@ -338,6 +397,19 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* mcs data can not be zero length */
|
||||
if ((len <= 0) || (len > 16 * 1024))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, len))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* make a copy of client mcs data */
|
||||
init_stream(self->client_mcs_data, len);
|
||||
out_uint8a(self->client_mcs_data, s->p, len);
|
||||
@ -372,6 +444,12 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, opcode);
|
||||
|
||||
@ -381,11 +459,22 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 2);
|
||||
in_uint8s(s, 2);
|
||||
|
||||
if (opcode & 2)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint16_be(s, self->userid);
|
||||
}
|
||||
|
||||
@ -416,6 +505,12 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, opcode);
|
||||
|
||||
if ((opcode >> 2) != MCS_AURQ)
|
||||
@ -426,6 +521,11 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
|
||||
|
||||
if (opcode & 2)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint16_be(s, self->userid);
|
||||
}
|
||||
|
||||
@ -491,6 +591,12 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, opcode);
|
||||
|
||||
if ((opcode >> 2) != MCS_CJRQ)
|
||||
@ -499,10 +605,21 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 4);
|
||||
|
||||
if (opcode & 2)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 2);
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer)
|
||||
init_stream(self->out_s, 16384);
|
||||
self->orders_state.clip_right = 1; /* silly rdp right clip */
|
||||
self->orders_state.clip_bottom = 1; /* silly rdp bottom clip */
|
||||
self->jpeg_han = xrdp_jpeg_init();
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -59,6 +60,7 @@ xrdp_orders_delete(struct xrdp_orders *self)
|
||||
return;
|
||||
}
|
||||
|
||||
xrdp_jpeg_deinit(self->jpeg_han);
|
||||
free_stream(self->out_s);
|
||||
g_free(self->orders_state.text_data);
|
||||
g_free(self);
|
||||
@ -2394,7 +2396,7 @@ xrdp_orders_send_bitmap3(struct xrdp_orders *self,
|
||||
make_stream(temp_s);
|
||||
init_stream(temp_s, 16384);
|
||||
quality = ci->jpeg_prop[0];
|
||||
xrdp_jpeg_compress(data, width, height, xr_s, bpp, 16384,
|
||||
xrdp_jpeg_compress(self->jpeg_han, data, width, height, xr_s, bpp, 16384,
|
||||
height - 1, temp_s, e, quality);
|
||||
s_mark_end(xr_s);
|
||||
bufsize = (int)(xr_s->end - xr_s->data);
|
||||
|
@ -514,6 +514,11 @@ xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self)
|
||||
|
||||
p = &(self->sec_layer->client_mcs_data);
|
||||
p->p = p->data;
|
||||
if (!s_check_rem(p, 31 + 2 + 2 + 120 + 2))
|
||||
{
|
||||
g_writeln("xrdp_rdp_parse_client_mcs_data: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(p, 31);
|
||||
in_uint16_le(p, self->client_info.width);
|
||||
in_uint16_le(p, self->client_info.height);
|
||||
@ -524,6 +529,10 @@ xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self)
|
||||
switch (i)
|
||||
{
|
||||
case 0xca01:
|
||||
if (!s_check_rem(p, 6 + 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(p, 6);
|
||||
in_uint8(p, i);
|
||||
|
||||
@ -837,6 +846,11 @@ xrdp_process_capset_general(struct xrdp_rdp *self, struct stream *s,
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len < 10 + 2)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_general: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 10);
|
||||
in_uint16_le(s, i);
|
||||
/* use_compact_packets is pretty much 'use rdp5' */
|
||||
@ -858,6 +872,11 @@ xrdp_process_capset_order(struct xrdp_rdp *self, struct stream *s,
|
||||
int cap_flags;
|
||||
|
||||
DEBUG(("order capabilities"));
|
||||
if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_order: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 20); /* Terminal desc, pad */
|
||||
in_uint8s(s, 2); /* Cache X granularity */
|
||||
in_uint8s(s, 2); /* Cache Y granularity */
|
||||
@ -915,13 +934,32 @@ static int APP_CC
|
||||
xrdp_process_capset_bmpcache(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_bmpcache: error");
|
||||
return 1;
|
||||
}
|
||||
self->client_info.bitmap_cache_version |= 1;
|
||||
in_uint8s(s, 24);
|
||||
in_uint16_le(s, self->client_info.cache1_entries);
|
||||
/* cache 1 */
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache1_entries = i;
|
||||
in_uint16_le(s, self->client_info.cache1_size);
|
||||
in_uint16_le(s, self->client_info.cache2_entries);
|
||||
/* cache 2 */
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache2_entries = i;
|
||||
in_uint16_le(s, self->client_info.cache2_size);
|
||||
in_uint16_le(s, self->client_info.cache3_entries);
|
||||
/* caceh 3 */
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache3_entries = i;
|
||||
in_uint16_le(s, self->client_info.cache3_size);
|
||||
DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries,
|
||||
self->client_info.cache1_size));
|
||||
@ -941,22 +979,30 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp *self, struct stream *s,
|
||||
int Bpp = 0;
|
||||
int i = 0;
|
||||
|
||||
if (len < 2 + 2 + 4 + 4 + 4)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_bmpcache2: error");
|
||||
return 1;
|
||||
}
|
||||
self->client_info.bitmap_cache_version |= 2;
|
||||
Bpp = (self->client_info.bpp + 7) / 8;
|
||||
in_uint16_le(s, i); /* cache flags */
|
||||
self->client_info.bitmap_cache_persist_enable = i;
|
||||
in_uint8s(s, 2); /* number of caches in set, 3 */
|
||||
in_uint32_le(s, i);
|
||||
i = MIN(i, 2000);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache1_entries = i;
|
||||
self->client_info.cache1_size = 256 * Bpp;
|
||||
in_uint32_le(s, i);
|
||||
i = MIN(i, 2000);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache2_entries = i;
|
||||
self->client_info.cache2_size = 1024 * Bpp;
|
||||
in_uint32_le(s, i);
|
||||
i = i & 0x7fffffff;
|
||||
i = MIN(i, 2000);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache3_entries = i;
|
||||
self->client_info.cache3_size = 4096 * Bpp;
|
||||
DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries,
|
||||
@ -975,6 +1021,11 @@ xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s,
|
||||
{
|
||||
int codec_id;
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_cache_v3_codec_id: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, codec_id);
|
||||
g_writeln("xrdp_process_capset_cache_v3_codec_id: cache_v3_codec_id %d",
|
||||
codec_id);
|
||||
@ -992,6 +1043,11 @@ xrdp_process_capset_pointercache(struct xrdp_rdp *self, struct stream *s,
|
||||
int colorPointerFlag;
|
||||
int no_new_cursor;
|
||||
|
||||
if (len < 2 + 2 + 2)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_pointercache: error");
|
||||
return 1;
|
||||
}
|
||||
no_new_cursor = self->client_info.pointer_flags & 2;
|
||||
in_uint16_le(s, colorPointerFlag);
|
||||
self->client_info.pointer_flags = colorPointerFlag;
|
||||
@ -1028,6 +1084,11 @@ xrdp_process_capset_brushcache(struct xrdp_rdp *self, struct stream *s,
|
||||
{
|
||||
int code;
|
||||
|
||||
if (len < 4)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_brushcache: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, code);
|
||||
self->client_info.brush_cache_code = code;
|
||||
return 0;
|
||||
@ -1040,12 +1101,11 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s,
|
||||
{
|
||||
int i32;
|
||||
|
||||
if (len - 4 < 8)
|
||||
if (len < 4 + 2 + 2)
|
||||
{
|
||||
g_writeln("xrdp_process_offscreen_bmpcache: bad len");
|
||||
g_writeln("xrdp_process_offscreen_bmpcache: error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint32_le(s, i32);
|
||||
self->client_info.offscreen_support_level = i32;
|
||||
in_uint16_le(s, i32);
|
||||
@ -1066,12 +1126,11 @@ xrdp_process_capset_rail(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
{
|
||||
int i32;
|
||||
|
||||
if (len - 4 < 4)
|
||||
if (len < 4)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_rail: bad len");
|
||||
g_writeln("xrdp_process_capset_rail: error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint32_le(s, i32);
|
||||
self->client_info.rail_support_level = i32;
|
||||
g_writeln("xrdp_process_capset_rail: rail_support_level %d",
|
||||
@ -1085,12 +1144,11 @@ xrdp_process_capset_window(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
{
|
||||
int i32;
|
||||
|
||||
if (len - 4 < 7)
|
||||
if (len < 4 + 1 + 2)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_window: bad len");
|
||||
g_writeln("xrdp_process_capset_window: error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint32_le(s, i32);
|
||||
self->client_info.wnd_support_level = i32;
|
||||
in_uint8(s, i32);
|
||||
@ -1117,14 +1175,32 @@ xrdp_process_capset_codecs(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
char *codec_guid;
|
||||
char *next_guid;
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_codecs: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, codec_count);
|
||||
len--;
|
||||
|
||||
for (index = 0; index < codec_count; index++)
|
||||
{
|
||||
codec_guid = s->p;
|
||||
if (len < 16 + 1 + 2)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_codecs: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 16);
|
||||
in_uint8(s, codec_id);
|
||||
in_uint16_le(s, codec_properties_length);
|
||||
len -= 16 + 1 + 2;
|
||||
if (len < codec_properties_length)
|
||||
{
|
||||
g_writeln("xrdp_process_capset_codecs: error");
|
||||
return 1;
|
||||
}
|
||||
len -= codec_properties_length;
|
||||
next_guid = s->p + codec_properties_length;
|
||||
|
||||
if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0)
|
||||
@ -1190,9 +1266,19 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
for (index = 0; index < num_caps; index++)
|
||||
{
|
||||
p = s->p;
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
g_writeln("xrdp_rdp_process_confirm_active: error 1");
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, type);
|
||||
in_uint16_le(s, len);
|
||||
|
||||
if ((len < 4) || !s_check_rem(s, len - 4))
|
||||
{
|
||||
g_writeln("xrdp_rdp_process_confirm_active: error len %d", len, s->end - s->p);
|
||||
return 1;
|
||||
}
|
||||
len -= 4;
|
||||
switch (type)
|
||||
{
|
||||
case RDP_CAPSET_GENERAL: /* 1 */
|
||||
@ -1278,7 +1364,7 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
break;
|
||||
}
|
||||
|
||||
s->p = p + len;
|
||||
s->p = p + len + 4;
|
||||
}
|
||||
|
||||
DEBUG(("out xrdp_rdp_process_confirm_active"));
|
||||
@ -1305,12 +1391,20 @@ xrdp_rdp_process_data_input(struct xrdp_rdp *self, struct stream *s)
|
||||
int param2;
|
||||
int time;
|
||||
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, num_events);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
DEBUG(("in xrdp_rdp_process_data_input %d events", num_events));
|
||||
|
||||
for (index = 0; index < num_events; index++)
|
||||
{
|
||||
if (!s_check_rem(s, 12))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, time);
|
||||
in_uint16_le(s, msg_type);
|
||||
in_uint16_le(s, device_flags);
|
||||
|
@ -331,12 +331,20 @@ unicode_in(struct stream *s, int uni_len, char *dst, int dst_len)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, dst[dst_index]);
|
||||
in_uint8s(s, 1);
|
||||
dst_index++;
|
||||
src_index += 2;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 2);
|
||||
return 0;
|
||||
}
|
||||
@ -359,6 +367,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
|
||||
|
||||
/* initialize (zero out) local variables */
|
||||
g_memset(tmpdata, 0, sizeof(char) * 256);
|
||||
if (!s_check_rem(s, 8))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 4);
|
||||
in_uint32_le(s, flags);
|
||||
DEBUG(("in xrdp_sec_process_logon_info flags $%x", flags));
|
||||
@ -398,6 +410,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
|
||||
}
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, len_domain);
|
||||
|
||||
if (len_domain > 511)
|
||||
@ -406,6 +422,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, len_user);
|
||||
|
||||
if (len_user > 511)
|
||||
@ -414,6 +434,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, len_password);
|
||||
|
||||
if (len_password > 511)
|
||||
@ -422,6 +446,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, len_program);
|
||||
|
||||
if (len_program > 511)
|
||||
@ -430,6 +458,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, len_directory);
|
||||
|
||||
if (len_directory > 511)
|
||||
@ -438,35 +470,75 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255);
|
||||
if (unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG(("domain %s", self->rdp_layer->client_info.domain));
|
||||
unicode_in(s, len_user, self->rdp_layer->client_info.username, 255);
|
||||
if (unicode_in(s, len_user, self->rdp_layer->client_info.username, 255) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG(("username %s", self->rdp_layer->client_info.username));
|
||||
|
||||
if (flags & RDP_LOGON_AUTO)
|
||||
{
|
||||
unicode_in(s, len_password, self->rdp_layer->client_info.password, 255);
|
||||
if (unicode_in(s, len_password, self->rdp_layer->client_info.password, 255) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG(("flag RDP_LOGON_AUTO found"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, len_password + 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, len_password + 2);
|
||||
if (self->rdp_layer->client_info.require_credentials)
|
||||
{
|
||||
g_writeln("xrdp_sec_process_logon_info: credentials on cmd line is mandatory");
|
||||
return 1; /* credentials on cmd line is mandatory */
|
||||
}
|
||||
}
|
||||
|
||||
unicode_in(s, len_program, self->rdp_layer->client_info.program, 255);
|
||||
if (unicode_in(s, len_program, self->rdp_layer->client_info.program, 255) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG(("program %s", self->rdp_layer->client_info.program));
|
||||
unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255);
|
||||
if (unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG(("directory %s", self->rdp_layer->client_info.directory));
|
||||
|
||||
if (flags & RDP_LOGON_BLOB)
|
||||
{
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 2); /* unknown */
|
||||
in_uint16_le(s, len_ip);
|
||||
unicode_in(s, len_ip - 2, tmpdata, 255);
|
||||
if (unicode_in(s, len_ip - 2, tmpdata, 255) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, len_dll);
|
||||
unicode_in(s, len_dll - 2, tmpdata, 255);
|
||||
if (unicode_in(s, len_dll - 2, tmpdata, 255) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem(s, 4 + 62 + 22 + 62 + 26 + 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, tzone); /* len of timetone */
|
||||
in_uint8s(s, 62); /* skip */
|
||||
in_uint8s(s, 22); /* skip misc. */
|
||||
@ -676,17 +748,29 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, flags);
|
||||
DEBUG((" in xrdp_sec_recv flags $%x", flags));
|
||||
|
||||
if (flags & SEC_ENCRYPT) /* 0x08 */
|
||||
{
|
||||
if (!s_check_rem(s, 8))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 8); /* signature */
|
||||
xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p));
|
||||
}
|
||||
|
||||
if (flags & SEC_CLIENT_RANDOM) /* 0x01 */
|
||||
{
|
||||
if (!s_check_rem(s, 4 + 64))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, len);
|
||||
in_uint8a(s, self->client_crypt_random, 64);
|
||||
xrdp_sec_rsa_op(self->client_random, self->client_crypt_random,
|
||||
@ -836,16 +920,30 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint32_le(s, num_channels);
|
||||
|
||||
if (num_channels > 31)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (index = 0; index < num_channels; index++)
|
||||
{
|
||||
channel_item = (struct mcs_channel_item *)
|
||||
g_malloc(sizeof(struct mcs_channel_item), 1);
|
||||
if (!s_check_rem(s, 12))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8a(s, channel_item->name, 8);
|
||||
in_uint32_le(s, channel_item->flags);
|
||||
channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1);
|
||||
list_add_item(self->mcs_layer->channel_list, (long)channel_item);
|
||||
list_add_item(self->mcs_layer->channel_list, (tintptr)channel_item);
|
||||
DEBUG(("got channel flags %8.8x name %s", channel_item->flags,
|
||||
channel_item->name));
|
||||
}
|
||||
@ -864,10 +962,14 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self)
|
||||
int tag = 0;
|
||||
int size = 0;
|
||||
|
||||
s = &self->client_mcs_data;
|
||||
s = &(self->client_mcs_data);
|
||||
/* set p to beginning */
|
||||
s->p = s->data;
|
||||
/* skip header */
|
||||
if (!s_check_rem(s, 23))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 23);
|
||||
|
||||
while (s_check_rem(s, 4))
|
||||
@ -890,7 +992,10 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self)
|
||||
case SEC_TAG_CLI_CRYPT:
|
||||
break;
|
||||
case SEC_TAG_CLI_CHANNELS:
|
||||
xrdp_sec_process_mcs_data_channels(self, s);
|
||||
if (xrdp_sec_process_mcs_data_channels(self, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SEC_TAG_CLI_4:
|
||||
break;
|
||||
@ -999,7 +1104,7 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* process the mcs client data we received from the mcs layer */
|
||||
static void APP_CC
|
||||
static int APP_CC
|
||||
xrdp_sec_in_mcs_data(struct xrdp_sec *self)
|
||||
{
|
||||
struct stream *s = (struct stream *)NULL;
|
||||
@ -1011,6 +1116,10 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
|
||||
s = &(self->client_mcs_data);
|
||||
/* get hostname, its unicode */
|
||||
s->p = s->data;
|
||||
if (!s_check_rem(s, 47))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 47);
|
||||
g_memset(client_info->hostname, 0, 32);
|
||||
c = 1;
|
||||
@ -1018,6 +1127,10 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
|
||||
|
||||
while (index < 16 && c != 0)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, c);
|
||||
in_uint8s(s, 1);
|
||||
client_info->hostname[index] = c;
|
||||
@ -1026,13 +1139,22 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
|
||||
|
||||
/* get build */
|
||||
s->p = s->data;
|
||||
if (!s_check_rem(s, 43 + 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 43);
|
||||
in_uint32_le(s, client_info->build);
|
||||
/* get keylayout */
|
||||
s->p = s->data;
|
||||
if (!s_check_rem(s, 39 + 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 39);
|
||||
in_uint32_le(s, client_info->keylayout);
|
||||
s->p = s->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -1105,7 +1227,10 @@ xrdp_sec_incoming(struct xrdp_sec *self)
|
||||
(int)(self->server_mcs_data.end - self->server_mcs_data.data));
|
||||
#endif
|
||||
DEBUG((" out xrdp_sec_incoming"));
|
||||
xrdp_sec_in_mcs_data(self);
|
||||
if (xrdp_sec_in_mcs_data(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,143 @@ int g_exec_pid = 0;
|
||||
/* this variable gets bumped up once per DVC we create */
|
||||
tui32 g_dvc_chan_id = 100;
|
||||
|
||||
struct timeout_obj
|
||||
{
|
||||
tui32 mstime;
|
||||
void* data;
|
||||
void (*callback)(void* data);
|
||||
struct timeout_obj* next;
|
||||
};
|
||||
|
||||
static struct timeout_obj *g_timeout_head = 0;
|
||||
static struct timeout_obj *g_timeout_tail = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
add_timeout(int msoffset, void (*callback)(void *data), void *data)
|
||||
{
|
||||
struct timeout_obj *tobj;
|
||||
tui32 now;
|
||||
|
||||
LOG(10, ("add_timeout:"));
|
||||
now = g_time3();
|
||||
tobj = g_malloc(sizeof(struct timeout_obj), 1);
|
||||
tobj->mstime = now + msoffset;
|
||||
tobj->callback = callback;
|
||||
tobj->data = data;
|
||||
if (g_timeout_tail == 0)
|
||||
{
|
||||
g_timeout_head = tobj;
|
||||
g_timeout_tail = tobj;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_timeout_tail->next = tobj;
|
||||
g_timeout_tail = tobj;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
get_timeout(int *timeout)
|
||||
{
|
||||
struct timeout_obj *tobj;
|
||||
tui32 now;
|
||||
int ltimeout;
|
||||
|
||||
LOG(10, ("get_timeout:"));
|
||||
ltimeout = *timeout;
|
||||
if (ltimeout < 1)
|
||||
{
|
||||
ltimeout = 0;
|
||||
}
|
||||
tobj = g_timeout_head;
|
||||
if (tobj != 0)
|
||||
{
|
||||
now = g_time3();
|
||||
while (tobj != 0)
|
||||
{
|
||||
LOG(10, (" now %u tobj->mstime %u", now, tobj->mstime));
|
||||
if (now < tobj->mstime)
|
||||
{
|
||||
ltimeout = tobj->mstime - now;
|
||||
}
|
||||
tobj = tobj->next;
|
||||
}
|
||||
}
|
||||
if (ltimeout > 0)
|
||||
{
|
||||
LOG(10, (" ltimeout %d", ltimeout));
|
||||
if (*timeout < 1)
|
||||
{
|
||||
*timeout = ltimeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*timeout > ltimeout)
|
||||
{
|
||||
*timeout = ltimeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
check_timeout(void)
|
||||
{
|
||||
struct timeout_obj *tobj;
|
||||
struct timeout_obj *last_tobj;
|
||||
struct timeout_obj *temp_tobj;
|
||||
int count;
|
||||
tui32 now;
|
||||
|
||||
LOG(10, ("check_timeout:"));
|
||||
count = 0;
|
||||
tobj = g_timeout_head;
|
||||
if (tobj != 0)
|
||||
{
|
||||
last_tobj = 0;
|
||||
while (tobj != 0)
|
||||
{
|
||||
count++;
|
||||
now = g_time3();
|
||||
if (now >= tobj->mstime)
|
||||
{
|
||||
tobj->callback(tobj->data);
|
||||
if (last_tobj == 0)
|
||||
{
|
||||
g_timeout_head = tobj->next;
|
||||
if (g_timeout_head == 0)
|
||||
{
|
||||
g_timeout_tail = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_tobj->next = tobj->next;
|
||||
if (g_timeout_tail == tobj)
|
||||
{
|
||||
g_timeout_tail = last_tobj;
|
||||
}
|
||||
}
|
||||
temp_tobj = tobj;
|
||||
tobj = tobj->next;
|
||||
g_free(temp_tobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
last_tobj = tobj;
|
||||
tobj = tobj->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(10, (" count %d", count));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int DEFAULT_CC
|
||||
g_is_term(void)
|
||||
@ -156,11 +293,11 @@ send_data_from_chan_item(struct chan_item *chan_item)
|
||||
out_uint32_le(s, cod->s->size);
|
||||
out_uint8a(s, cod->s->p, size);
|
||||
s_mark_end(s);
|
||||
LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- "
|
||||
LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- "
|
||||
"size %d chan_flags 0x%8.8x", size, chan_flags));
|
||||
g_sent = 1;
|
||||
error = trans_force_write(g_con_trans);
|
||||
|
||||
error = trans_write_copy(g_con_trans);
|
||||
if (error != 0)
|
||||
{
|
||||
return 1;
|
||||
@ -255,7 +392,7 @@ send_init_response_message(void)
|
||||
out_uint32_le(s, 2); /* msg id */
|
||||
out_uint32_le(s, 8); /* size */
|
||||
s_mark_end(s);
|
||||
return trans_force_write(g_con_trans);
|
||||
return trans_write_copy(g_con_trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -278,7 +415,7 @@ send_channel_setup_response_message(void)
|
||||
out_uint32_le(s, 4); /* msg id */
|
||||
out_uint32_le(s, 8); /* size */
|
||||
s_mark_end(s);
|
||||
return trans_force_write(g_con_trans);
|
||||
return trans_write_copy(g_con_trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -301,7 +438,7 @@ send_channel_data_response_message(void)
|
||||
out_uint32_le(s, 6); /* msg id */
|
||||
out_uint32_le(s, 8); /* size */
|
||||
s_mark_end(s);
|
||||
return trans_force_write(g_con_trans);
|
||||
return trans_write_copy(g_con_trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -500,7 +637,7 @@ process_message_channel_data(struct stream *s)
|
||||
if (chan_flags & 2) /* last */
|
||||
{
|
||||
s_mark_end(ls);
|
||||
trans_force_write(g_api_con_trans);
|
||||
trans_write_copy(g_api_con_trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -904,7 +1041,9 @@ THREAD_RV THREAD_CC
|
||||
channel_thread_loop(void *in_val)
|
||||
{
|
||||
tbus objs[32];
|
||||
tbus wobjs[32];
|
||||
int num_objs;
|
||||
int num_wobjs;
|
||||
int timeout;
|
||||
int error;
|
||||
THREAD_RV rv;
|
||||
@ -918,13 +1057,15 @@ channel_thread_loop(void *in_val)
|
||||
{
|
||||
timeout = -1;
|
||||
num_objs = 0;
|
||||
num_wobjs = 0;
|
||||
objs[num_objs] = g_term_event;
|
||||
num_objs++;
|
||||
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
|
||||
trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
|
||||
|
||||
while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0)
|
||||
while (g_obj_wait(objs, num_objs, wobjs, num_wobjs, timeout) == 0)
|
||||
{
|
||||
check_timeout();
|
||||
if (g_is_wait_obj_set(g_term_event))
|
||||
{
|
||||
LOGM((LOG_LEVEL_INFO, "channel_thread_loop: g_term_event set"));
|
||||
@ -997,16 +1138,19 @@ channel_thread_loop(void *in_val)
|
||||
xfuse_check_wait_objs();
|
||||
timeout = -1;
|
||||
num_objs = 0;
|
||||
num_wobjs = 0;
|
||||
objs[num_objs] = g_term_event;
|
||||
num_objs++;
|
||||
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
|
||||
trans_get_wait_objs(g_con_trans, objs, &num_objs);
|
||||
trans_get_wait_objs_rw(g_con_trans, objs, &num_objs,
|
||||
wobjs, &num_wobjs);
|
||||
trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
|
||||
trans_get_wait_objs(g_api_con_trans, objs, &num_objs);
|
||||
xcommon_get_wait_objs(objs, &num_objs, &timeout);
|
||||
sound_get_wait_objs(objs, &num_objs, &timeout);
|
||||
dev_redir_get_wait_objs(objs, &num_objs, &timeout);
|
||||
xfuse_get_wait_objs(objs, &num_objs, &timeout);
|
||||
get_timeout(&timeout);
|
||||
} /* end while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) */
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2009-2012
|
||||
* Copyright (C) Laxmikant Rashinkar 2009-2012
|
||||
* Copyright (C) Jay Sorg 2009-2013
|
||||
* Copyright (C) Laxmikant Rashinkar 2009-2013
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -59,6 +59,7 @@ g_is_term(void);
|
||||
|
||||
int APP_CC send_channel_data(int chan_id, char *data, int size);
|
||||
int APP_CC main_cleanup(void);
|
||||
int APP_CC add_timeout(int msoffset, void (*callback)(void* data), void* data);
|
||||
int APP_CC find_empty_slot_in_dvc_channels();
|
||||
struct xrdp_api_data * APP_CC struct_from_dvc_chan_id(tui32 dvc_chan_id);
|
||||
int remove_struct_with_chan_id(tui32 dvc_chan_id);
|
||||
|
@ -587,53 +587,50 @@ void dev_redir_proc_client_core_cap_resp(struct stream *s)
|
||||
tui16 cap_type;
|
||||
tui16 cap_len;
|
||||
tui32 cap_version;
|
||||
char* holdp;
|
||||
|
||||
xstream_rd_u16_le(s, num_caps);
|
||||
xstream_seek(s, 2); /* padding */
|
||||
|
||||
for (i = 0; i < num_caps; i++)
|
||||
{
|
||||
holdp = s->p;
|
||||
xstream_rd_u16_le(s, cap_type);
|
||||
xstream_rd_u16_le(s, cap_len);
|
||||
xstream_rd_u32_le(s, cap_version);
|
||||
|
||||
/* remove header length and version */
|
||||
cap_len -= 8;
|
||||
|
||||
switch (cap_type)
|
||||
{
|
||||
case CAP_GENERAL_TYPE:
|
||||
log_debug("got CAP_GENERAL_TYPE");
|
||||
xstream_seek(s, cap_len);
|
||||
break;
|
||||
|
||||
case CAP_PRINTER_TYPE:
|
||||
log_debug("got CAP_PRINTER_TYPE");
|
||||
g_is_printer_redir_supported = 1;
|
||||
xstream_seek(s, cap_len);
|
||||
break;
|
||||
|
||||
case CAP_PORT_TYPE:
|
||||
log_debug("got CAP_PORT_TYPE");
|
||||
g_is_port_redir_supported = 1;
|
||||
xstream_seek(s, cap_len);
|
||||
break;
|
||||
|
||||
case CAP_DRIVE_TYPE:
|
||||
log_debug("got CAP_DRIVE_TYPE");
|
||||
g_is_drive_redir_supported = 1;
|
||||
if (cap_version == 2)
|
||||
{
|
||||
g_drive_redir_version = 2;
|
||||
xstream_seek(s, cap_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case CAP_SMARTCARD_TYPE:
|
||||
log_debug("got CAP_SMARTCARD_TYPE");
|
||||
g_is_smartcard_redir_supported = 1;
|
||||
scard_init();
|
||||
xstream_seek(s, cap_len);
|
||||
break;
|
||||
}
|
||||
s->p = holdp + cap_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ struct irp
|
||||
|
||||
void (*callback)(struct stream *s, IRP *irp, tui32 DeviceId,
|
||||
tui32 CompletionId, tui32 IoStatus);
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
IRP * APP_CC devredir_irp_new(void);
|
||||
|
12
sesman/chansrv/pcsc/Makefile
Normal file
12
sesman/chansrv/pcsc/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
OBJS = xrdp_pcsc.o
|
||||
|
||||
CFLAGS = -Wall -O2 -fPIC
|
||||
|
||||
all: libpcsclite.so
|
||||
|
||||
libpcsclite.so: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -shared -o libpcsclite.so $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) libpcsclite.so
|
856
sesman/chansrv/pcsc/xrdp_pcsc.c
Normal file
856
sesman/chansrv/pcsc/xrdp_pcsc.c
Normal file
@ -0,0 +1,856 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define PCSC_API
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef BYTE *LPBYTE;
|
||||
typedef unsigned int LONG;
|
||||
typedef unsigned int DWORD;
|
||||
typedef DWORD *LPDWORD;
|
||||
typedef const void *LPCVOID;
|
||||
typedef const char *LPCSTR;
|
||||
typedef char *LPSTR;
|
||||
typedef void *LPVOID;
|
||||
typedef const BYTE *LPCBYTE;
|
||||
|
||||
typedef LONG SCARDCONTEXT;
|
||||
typedef SCARDCONTEXT *LPSCARDCONTEXT;
|
||||
|
||||
typedef LONG SCARDHANDLE;
|
||||
typedef SCARDHANDLE *LPSCARDHANDLE;
|
||||
|
||||
#define MAX_ATR_SIZE 33
|
||||
|
||||
typedef struct _SCARD_READERSTATE
|
||||
{
|
||||
const char *szReader;
|
||||
void *pvUserData;
|
||||
DWORD dwCurrentState;
|
||||
DWORD dwEventState;
|
||||
DWORD cbAtr;
|
||||
unsigned char rgbAtr[MAX_ATR_SIZE];
|
||||
} SCARD_READERSTATE, *LPSCARD_READERSTATE;
|
||||
|
||||
typedef struct _SCARD_IO_REQUEST
|
||||
{
|
||||
unsigned long dwProtocol;
|
||||
unsigned long cbPciLength;
|
||||
} SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST;
|
||||
|
||||
#define LLOG_LEVEL 5
|
||||
#define LLOGLN(_level, _args) \
|
||||
do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0)
|
||||
|
||||
#define SCARD_ESTABLISH_CONTEXT 0x01
|
||||
#define SCARD_RELEASE_CONTEXT 0x02
|
||||
#define SCARD_LIST_READERS 0x03
|
||||
#define SCARD_CONNECT 0x04
|
||||
#define SCARD_RECONNECT 0x05
|
||||
#define SCARD_DISCONNECT 0x06
|
||||
#define SCARD_BEGIN_TRANSACTION 0x07
|
||||
#define SCARD_END_TRANSACTION 0x08
|
||||
#define SCARD_TRANSMIT 0x09
|
||||
#define SCARD_CONTROL 0x0A
|
||||
#define SCARD_STATUS 0x0B
|
||||
#define SCARD_GET_STATUS_CHANGE 0x0C
|
||||
#define SCARD_CANCEL 0x0D
|
||||
#define SCARD_CANCEL_TRANSACTION 0x0E
|
||||
#define SCARD_GET_ATTRIB 0x0F
|
||||
#define SCARD_SET_ATTRIB 0x10
|
||||
|
||||
#define SCARD_S_SUCCESS 0x00000000
|
||||
#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001)
|
||||
|
||||
#define SET_UINT32(_data, _offset, _val) do { \
|
||||
(((BYTE*)(_data)) + (_offset))[0] = ((_val) >> 0) & 0xff; \
|
||||
(((BYTE*)(_data)) + (_offset))[1] = ((_val) >> 8) & 0xff; \
|
||||
(((BYTE*)(_data)) + (_offset))[2] = ((_val) >> 16) & 0xff; \
|
||||
(((BYTE*)(_data)) + (_offset))[3] = ((_val) >> 24) & 0xff; } while (0)
|
||||
|
||||
#define GET_UINT32(_data, _offset) \
|
||||
((((BYTE*)(_data)) + (_offset))[0] << 0) | \
|
||||
((((BYTE*)(_data)) + (_offset))[1] << 8) | \
|
||||
((((BYTE*)(_data)) + (_offset))[2] << 16) | \
|
||||
((((BYTE*)(_data)) + (_offset))[3] << 24)
|
||||
|
||||
#define LMIN(_val1, _val2) (_val1) < (_val2) ? (_val1) : (_val2)
|
||||
#define LMAX(_val1, _val2) (_val1) > (_val2) ? (_val1) : (_val2)
|
||||
|
||||
static int g_sck = -1; /* unix domain socket */
|
||||
|
||||
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* for pcsc_stringify_error */
|
||||
static char g_error_str[512];
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
get_display_num_from_display(const char *display_text)
|
||||
{
|
||||
int rv;
|
||||
int index;
|
||||
int mode;
|
||||
int host_index;
|
||||
int disp_index;
|
||||
int scre_index;
|
||||
char host[256];
|
||||
char disp[256];
|
||||
char scre[256];
|
||||
|
||||
memset(host, 0, 256);
|
||||
memset(disp, 0, 256);
|
||||
memset(scre, 0, 256);
|
||||
|
||||
index = 0;
|
||||
host_index = 0;
|
||||
disp_index = 0;
|
||||
scre_index = 0;
|
||||
mode = 0;
|
||||
|
||||
while (display_text[index] != 0)
|
||||
{
|
||||
if (display_text[index] == ':')
|
||||
{
|
||||
mode = 1;
|
||||
}
|
||||
else if (display_text[index] == '.')
|
||||
{
|
||||
mode = 2;
|
||||
}
|
||||
else if (mode == 0)
|
||||
{
|
||||
host[host_index] = display_text[index];
|
||||
host_index++;
|
||||
}
|
||||
else if (mode == 1)
|
||||
{
|
||||
disp[disp_index] = display_text[index];
|
||||
disp_index++;
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
scre[scre_index] = display_text[index];
|
||||
scre_index++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
host[host_index] = 0;
|
||||
disp[disp_index] = 0;
|
||||
scre[scre_index] = 0;
|
||||
LLOGLN(0, ("get_display_num_from_display: host [%s] disp [%s] scre [%s]",
|
||||
host, disp, scre));
|
||||
rv = atoi(disp);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
connect_to_chansrv(void)
|
||||
{
|
||||
int bytes;
|
||||
int dis;
|
||||
int error;
|
||||
char *xrdp_session;
|
||||
char *xrdp_display;
|
||||
char *home_str;
|
||||
struct sockaddr_un saddr;
|
||||
struct sockaddr *psaddr;
|
||||
|
||||
if (g_sck != -1)
|
||||
{
|
||||
/* already connected */
|
||||
return 0;
|
||||
}
|
||||
xrdp_session = getenv("XRDP_SESSION");
|
||||
if (xrdp_session == NULL)
|
||||
{
|
||||
/* XRDP_SESSION must be set */
|
||||
LLOGLN(0, ("connect_to_chansrv: error, not xrdp session"));
|
||||
return 1;
|
||||
}
|
||||
xrdp_display = getenv("DISPLAY");
|
||||
if (xrdp_display == NULL)
|
||||
{
|
||||
/* DISPLAY must be set */
|
||||
LLOGLN(0, ("connect_to_chansrv: error, display not set"));
|
||||
return 1;
|
||||
}
|
||||
home_str = getenv("HOME");
|
||||
if (home_str == NULL)
|
||||
{
|
||||
/* HOME must be set */
|
||||
LLOGLN(0, ("connect_to_chansrv: error, home not set"));
|
||||
return 1;
|
||||
}
|
||||
dis = get_display_num_from_display(xrdp_display);
|
||||
if (dis < 10)
|
||||
{
|
||||
/* DISPLAY must be > 9 */
|
||||
LLOGLN(0, ("connect_to_chansrv: error, display not > 9 %d", dis));
|
||||
return 1;
|
||||
}
|
||||
g_sck = socket(PF_LOCAL, SOCK_STREAM, 0);
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("connect_to_chansrv: error, socket failed"));
|
||||
return 1;
|
||||
}
|
||||
memset(&saddr, 0, sizeof(struct sockaddr_un));
|
||||
saddr.sun_family = AF_UNIX;
|
||||
bytes = sizeof(saddr.sun_path);
|
||||
snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis);
|
||||
saddr.sun_path[bytes - 1] = 0;
|
||||
LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path));
|
||||
psaddr = (struct sockaddr *) &saddr;
|
||||
bytes = sizeof(struct sockaddr_un);
|
||||
error = connect(g_sck, psaddr, bytes);
|
||||
if (error == 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("connect_to_chansrv");
|
||||
close(g_sck);
|
||||
g_sck = -1;
|
||||
LLOGLN(0, ("connect_to_chansrv: error, open %s", saddr.sun_path));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
send_message(int code, char *data, int bytes)
|
||||
{
|
||||
char header[8];
|
||||
|
||||
SET_UINT32(header, 0, bytes);
|
||||
SET_UINT32(header, 4, code);
|
||||
if (send(g_sck, header, 8, 0) != 8)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (send(g_sck, data, bytes, 0) != bytes)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
get_message(int *code, char *data, int *bytes)
|
||||
{
|
||||
char header[8];
|
||||
int max_bytes;
|
||||
|
||||
if (recv(g_sck, header, 8, 0) != 8)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
max_bytes = *bytes;
|
||||
*bytes = GET_UINT32(header, 0);
|
||||
*code = GET_UINT32(header, 4);
|
||||
if (*bytes > max_bytes)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (recv(g_sck, data, *bytes, 0) != *bytes)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2,
|
||||
LPSCARDCONTEXT phContext)
|
||||
{
|
||||
char msg[256];
|
||||
DWORD context;
|
||||
int code;
|
||||
int bytes;
|
||||
int status;
|
||||
|
||||
LLOGLN(0, ("SCardEstablishContext:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
if (connect_to_chansrv() != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardEstablishContext: error, can not connect "
|
||||
"to chansrv"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
SET_UINT32(msg, 0, dwScope);
|
||||
if (send_message(SCARD_ESTABLISH_CONTEXT, msg, 4) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardEstablishContext: error, send_message"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
bytes = 256;
|
||||
if (get_message(&code, msg, &bytes) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardEstablishContext: error, get_message"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
if ((code != SCARD_ESTABLISH_CONTEXT) || (bytes != 8))
|
||||
{
|
||||
LLOGLN(0, ("SCardEstablishContext: error, bad code"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
context = GET_UINT32(msg, 0);
|
||||
status = GET_UINT32(msg, 4);
|
||||
LLOGLN(10, ("SCardEstablishContext: got context 0x%8.8x", context));
|
||||
*phContext = context;
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardReleaseContext(SCARDCONTEXT hContext)
|
||||
{
|
||||
char msg[256];
|
||||
int code;
|
||||
int bytes;
|
||||
int status;
|
||||
|
||||
LLOGLN(0, ("SCardReleaseContext:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardReleaseContext: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
SET_UINT32(msg, 0, hContext);
|
||||
if (send_message(SCARD_RELEASE_CONTEXT, msg, 4) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardReleaseContext: error, send_message"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
bytes = 256;
|
||||
if (get_message(&code, msg, &bytes) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardReleaseContext: error, get_message"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
if ((code != SCARD_RELEASE_CONTEXT) || (bytes != 4))
|
||||
{
|
||||
LLOGLN(0, ("SCardReleaseContext: error, bad code"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
status = GET_UINT32(msg, 0);
|
||||
LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status));
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardIsValidContext(SCARDCONTEXT hContext)
|
||||
{
|
||||
LLOGLN(0, ("SCardIsValidContext:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardIsValidContext: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
|
||||
DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
|
||||
LPDWORD pdwActiveProtocol)
|
||||
{
|
||||
char msg[256];
|
||||
int code;
|
||||
int bytes;
|
||||
int status;
|
||||
int offset;
|
||||
|
||||
LLOGLN(0, ("SCardConnect:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardConnect: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
offset = 0;
|
||||
SET_UINT32(msg, offset, hContext);
|
||||
offset += 4;
|
||||
bytes = strlen(szReader);
|
||||
if (bytes > 99)
|
||||
{
|
||||
LLOGLN(0, ("SCardConnect: error, name too long"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
memcpy(msg + offset, szReader, bytes);
|
||||
memset(msg + bytes, 0, 100 - bytes);
|
||||
offset += 100;
|
||||
SET_UINT32(msg, offset, dwShareMode);
|
||||
offset += 4;
|
||||
SET_UINT32(msg, offset, dwPreferredProtocols);
|
||||
offset += 4;
|
||||
if (send_message(SCARD_CONNECT, msg, offset) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardConnect: error, send_message"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
bytes = 256;
|
||||
if (get_message(&code, msg, &bytes) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardConnect: error, get_message"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
if (code != SCARD_CONNECT)
|
||||
{
|
||||
LLOGLN(0, ("SCardConnect: error, bad code"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
*phCard = GET_UINT32(msg, 0);
|
||||
*pdwActiveProtocol = GET_UINT32(msg, 4);
|
||||
status = GET_UINT32(msg, 8);
|
||||
LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status));
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
|
||||
DWORD dwPreferredProtocols, DWORD dwInitialization,
|
||||
LPDWORD pdwActiveProtocol)
|
||||
{
|
||||
LLOGLN(0, ("SCardReconnect:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardReconnect: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
|
||||
{
|
||||
LLOGLN(0, ("SCardDisconnect:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardDisconnect: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardBeginTransaction(SCARDHANDLE hCard)
|
||||
{
|
||||
char msg[256];
|
||||
int code;
|
||||
int bytes;
|
||||
int status;
|
||||
|
||||
LLOGLN(0, ("SCardBeginTransaction:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardBeginTransaction: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
SET_UINT32(msg, 0, hCard);
|
||||
if (send_message(SCARD_BEGIN_TRANSACTION, msg, 4) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardBeginTransaction: error, send_message"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
bytes = 256;
|
||||
if (get_message(&code, msg, &bytes) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardBeginTransaction: error, get_message"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4))
|
||||
{
|
||||
LLOGLN(0, ("SCardBeginTransaction: error, bad code"));
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
status = GET_UINT32(msg, 0);
|
||||
LLOGLN(10, ("SCardBeginTransaction: got status 0x%8.8x", status));
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
|
||||
{
|
||||
LLOGLN(0, ("SCardEndTransaction:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardEndTransaction: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen,
|
||||
LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr,
|
||||
LPDWORD pcbAtrLen)
|
||||
{
|
||||
LLOGLN(0, ("SCardStatus:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardStatus: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
|
||||
LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
|
||||
{
|
||||
char *msg;
|
||||
int bytes;
|
||||
int code;
|
||||
int index;
|
||||
int offset;
|
||||
int str_len;
|
||||
int status;
|
||||
|
||||
LLOGLN(0, ("SCardGetStatusChange:"));
|
||||
LLOGLN(10, (" dwTimeout %d cReaders %d", dwTimeout, cReaders));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardGetStatusChange: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
msg = (char *) malloc(8192);
|
||||
SET_UINT32(msg, 0, hContext);
|
||||
SET_UINT32(msg, 4, dwTimeout);
|
||||
SET_UINT32(msg, 8, cReaders);
|
||||
offset = 12;
|
||||
for (index = 0; index < cReaders; index++)
|
||||
{
|
||||
str_len = strlen(rgReaderStates[index].szReader);
|
||||
str_len = LMIN(str_len, 99);
|
||||
memset(msg + offset, 0, 100);
|
||||
memcpy(msg + offset, rgReaderStates[index].szReader, str_len);
|
||||
offset += 100;
|
||||
LLOGLN(10, (" in dwCurrentState %d", rgReaderStates[index].dwCurrentState));
|
||||
SET_UINT32(msg, offset, rgReaderStates[index].dwCurrentState);
|
||||
offset += 4;
|
||||
LLOGLN(10, (" in dwEventState %d", rgReaderStates[index].dwEventState));
|
||||
SET_UINT32(msg, offset, rgReaderStates[index].dwEventState);
|
||||
offset += 4;
|
||||
LLOGLN(10, (" in cbAtr %d", rgReaderStates[index].cbAtr));
|
||||
SET_UINT32(msg, offset, rgReaderStates[index].cbAtr);
|
||||
offset += 4;
|
||||
memset(msg + offset, 0, 36);
|
||||
memcpy(msg + offset, rgReaderStates[index].rgbAtr, 33);
|
||||
offset += 36;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
if (send_message(SCARD_GET_STATUS_CHANGE, msg, offset) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardGetStatusChange: error, send_message"));
|
||||
free(msg);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
bytes = 8192;
|
||||
if (get_message(&code, msg, &bytes) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardGetStatusChange: error, get_message"));
|
||||
free(msg);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
if (code != SCARD_GET_STATUS_CHANGE)
|
||||
{
|
||||
LLOGLN(0, ("SCardGetStatusChange: error, bad code"));
|
||||
free(msg);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
cReaders = GET_UINT32(msg, 0);
|
||||
offset = 4;
|
||||
LLOGLN(10, ("SCardGetStatusChange: got back cReaders %d", cReaders));
|
||||
for (index = 0; index < cReaders; index++)
|
||||
{
|
||||
rgReaderStates[index].dwCurrentState = GET_UINT32(msg, offset);
|
||||
offset += 4;
|
||||
LLOGLN(10, (" out dwCurrentState %d", rgReaderStates[index].dwCurrentState));
|
||||
rgReaderStates[index].dwEventState = GET_UINT32(msg, offset);
|
||||
offset += 4;
|
||||
LLOGLN(10, (" out dwEventState %d", rgReaderStates[index].dwEventState));
|
||||
rgReaderStates[index].cbAtr = GET_UINT32(msg, offset);
|
||||
offset += 4;
|
||||
LLOGLN(10, (" out cbAtr %d", rgReaderStates[index].cbAtr));
|
||||
memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33);
|
||||
offset += 36;
|
||||
}
|
||||
status = GET_UINT32(msg, offset);
|
||||
offset += 4;
|
||||
free(msg);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
|
||||
DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
|
||||
LPDWORD lpBytesReturned)
|
||||
{
|
||||
LLOGLN(0, ("SCardControl:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardControl: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
|
||||
LPCBYTE pbSendBuffer, DWORD cbSendLength,
|
||||
SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
|
||||
LPDWORD pcbRecvLength)
|
||||
{
|
||||
LLOGLN(0, ("SCardTransmit:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardTransmit: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
|
||||
LPDWORD pcchGroups)
|
||||
{
|
||||
LLOGLN(0, ("SCardListReaderGroups:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardListReaderGroups: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
|
||||
LPDWORD pcchReaders)
|
||||
{
|
||||
char* msg;
|
||||
char* reader_names;
|
||||
int reader_names_index;
|
||||
int code;
|
||||
int bytes;
|
||||
int num_readers;
|
||||
int status;
|
||||
int offset;
|
||||
int index;
|
||||
char reader[100];
|
||||
|
||||
LLOGLN(0, ("SCardListReaders:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardListReaders: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
msg = (char *) malloc(8192);
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
SET_UINT32(msg, 0, hContext);
|
||||
if (send_message(SCARD_LIST_READERS, msg, 4) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardListReaders: error, send_message"));
|
||||
free(msg);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
bytes = 8192;
|
||||
if (get_message(&code, msg, &bytes) != 0)
|
||||
{
|
||||
LLOGLN(0, ("SCardListReaders: error, get_message"));
|
||||
free(msg);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
if (code != SCARD_LIST_READERS)
|
||||
{
|
||||
LLOGLN(0, ("SCardListReaders: error, bad code"));
|
||||
free(msg);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
offset = 0;
|
||||
num_readers = GET_UINT32(msg, offset);
|
||||
offset += 4;
|
||||
LLOGLN(10, ("hi - mszReaders %p pcchReaders %p num_readers %d", mszReaders, pcchReaders, num_readers));
|
||||
reader_names = (char *) malloc(8192);
|
||||
reader_names_index = 0;
|
||||
for (index = 0; index < num_readers; index++)
|
||||
{
|
||||
memcpy(reader, msg + offset, 100);
|
||||
bytes = strlen(reader);
|
||||
memcpy(reader_names + reader_names_index, reader, bytes);
|
||||
reader_names_index += bytes;
|
||||
reader_names[reader_names_index] = 0;
|
||||
reader_names_index++;
|
||||
offset += 100;
|
||||
LLOGLN(10, ("SCardListReaders: readername %s", reader));
|
||||
}
|
||||
reader_names[reader_names_index] = 0;
|
||||
reader_names_index++;
|
||||
status = GET_UINT32(msg, offset);
|
||||
offset += 4;
|
||||
if (pcchReaders != 0)
|
||||
{
|
||||
*pcchReaders = reader_names_index;
|
||||
}
|
||||
if (mszReaders != 0)
|
||||
{
|
||||
memcpy(mszReaders, reader_names, reader_names_index);
|
||||
}
|
||||
free(msg);
|
||||
free(reader_names);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
|
||||
{
|
||||
LLOGLN(0, ("SCardFreeMemory:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardFreeMemory: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardCancel(SCARDCONTEXT hContext)
|
||||
{
|
||||
LLOGLN(0, ("SCardCancel:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardCancel: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
|
||||
LPDWORD pcbAttrLen)
|
||||
{
|
||||
LLOGLN(0, ("SCardGetAttrib:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardGetAttrib: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
PCSC_API LONG
|
||||
SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
|
||||
DWORD cbAttrLen)
|
||||
{
|
||||
LLOGLN(0, ("SCardSetAttrib:"));
|
||||
if (g_sck == -1)
|
||||
{
|
||||
LLOGLN(0, ("SCardSetAttrib: error, not connected"));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
char *
|
||||
pcsc_stringify_error(const long code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case SCARD_S_SUCCESS:
|
||||
snprintf(g_error_str, 511, "Command successful.");
|
||||
break;
|
||||
case SCARD_F_INTERNAL_ERROR:
|
||||
snprintf(g_error_str, 511, "Internal error.");
|
||||
break;
|
||||
default:
|
||||
snprintf(g_error_str, 511, "error 0x%8.8x", (int)code);
|
||||
break;
|
||||
}
|
||||
g_error_str[511] = 0;
|
||||
return g_error_str;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -26,26 +26,92 @@
|
||||
|
||||
#include "parse.h"
|
||||
#include "irp.h"
|
||||
#include "trans.h"
|
||||
|
||||
#define SCARD_SHARE_EXCLUSIVE 0x00000001
|
||||
#define SCARD_SHARE_SHARED 0x00000002
|
||||
#define SCARD_SHARE_DIRECT 0x00000003
|
||||
|
||||
/* see [MS-RDPESC] 2.2.5 protocol identifier - Table A */
|
||||
#define SCARD_PROTOCOL_UNDEFINED 0x00000000
|
||||
#define SCARD_PROTOCOL_T0 0x00000001
|
||||
#define SCARD_PROTOCOL_T1 0x00000002
|
||||
#define SCARD_PROTOCOL_Tx 0x00000003
|
||||
#define SCARD_PROTOCOL_RAW 0x00010000
|
||||
|
||||
/* see [MS-RDPESC] 2.2.5 protocol identifier - Table B */
|
||||
#define SCARD_PROTOCOL_DEFAULT 0x80000000
|
||||
#define SCARD_PROTOCOL_OPTIMAL 0x00000000
|
||||
|
||||
/* initialization type */
|
||||
#define SCARD_LEAVE_CARD 0x00000000 /* do not do anything */
|
||||
#define SCARD_RESET_CARD 0x00000001 /* reset smart card */
|
||||
#define SCARD_UNPOWER_CARD 0x00000002 /* turn off and reset card */
|
||||
|
||||
typedef struct reader_state
|
||||
{
|
||||
char reader_name[128];
|
||||
tui32 current_state;
|
||||
tui32 event_state;
|
||||
tui32 atr_len; /* number of bytes in atr[] */
|
||||
tui8 atr[36];
|
||||
|
||||
/*
|
||||
* share mode flag, can be one of:
|
||||
* SCARD_SHARE_EXCLUSIVE app not willing to share smartcard with other apps
|
||||
* SCARD_SHARE_SHARED app willing to share smartcard with other apps
|
||||
* SCARD_SHARE_DIRECT app demands direct control of smart card, hence
|
||||
* it is not available to other readers
|
||||
*/
|
||||
tui32 shared_mode_flag;
|
||||
|
||||
/*
|
||||
* This field MUST have a value from Table A which is logically
|
||||
* OR'ed with a value from Table B.
|
||||
*/
|
||||
tui32 preferred_protocol;
|
||||
|
||||
/*
|
||||
* initialization type, must be one of the initialization type
|
||||
* defined above
|
||||
*/
|
||||
tui32 init_type;
|
||||
|
||||
} READER_STATE;
|
||||
|
||||
/* forward declarations */
|
||||
void scard_device_announce(tui32 device_id);
|
||||
int APP_CC scard_get_wait_objs(tbus *objs, int *count, int *timeout);
|
||||
int APP_CC scard_check_wait_objs(void);
|
||||
int APP_CC scard_init(void);
|
||||
int APP_CC scard_deinit(void);
|
||||
int APP_CC scard_send_establish_context(struct trans *con, int scope);
|
||||
int APP_CC scard_send_release_context(struct trans *con, tui32 context);
|
||||
int APP_CC scard_send_is_valid_context(struct trans *con, tui32 context);
|
||||
int APP_CC scard_send_list_readers(struct trans *con, tui32 context, int wide);
|
||||
|
||||
/* callbacks into this module */
|
||||
void scard_handle_EstablishContext_Return(struct stream *s, IRP *irp,
|
||||
tui32 DeviceId, tui32 CompletionId,
|
||||
tui32 IoStatus);
|
||||
int APP_CC scard_send_get_status_change(struct trans *con, tui32 context,
|
||||
int wide, tui32 timeout,
|
||||
tui32 num_readers, READER_STATE* rsa);
|
||||
|
||||
void scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
|
||||
tui32 DeviceId, tui32 CompletionId,
|
||||
tui32 IoStatus);
|
||||
int APP_CC scard_send_connect(struct trans *con, tui32 context, int wide,
|
||||
READER_STATE* rs);
|
||||
|
||||
int APP_CC
|
||||
scard_get_wait_objs(tbus *objs, int *count, int *timeout);
|
||||
int APP_CC
|
||||
scard_check_wait_objs(void);
|
||||
int APP_CC
|
||||
scard_init(void);
|
||||
int APP_CC
|
||||
scard_deinit(void);
|
||||
int APP_CC scard_send_reconnect(struct trans *con, tui32 context,
|
||||
tui32 sc_handle, READER_STATE* rs);
|
||||
|
||||
int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle);
|
||||
int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle);
|
||||
int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle);
|
||||
int APP_CC scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle);
|
||||
|
||||
/*
|
||||
SCardReconnect
|
||||
SCardTransmit
|
||||
SCardControl
|
||||
SCardListReaderGroups
|
||||
not needed: SCardFreeMemory
|
||||
SCardCancel
|
||||
SCardGetAttrib
|
||||
SCardSetAttrib
|
||||
*/
|
||||
#endif /* end #ifndef _SMARTCARD_C */
|
||||
|
@ -20,88 +20,46 @@
|
||||
/*
|
||||
* smartcard redirection support, PCSC daemon standin
|
||||
* this will act like pcsc daemon
|
||||
* pcsc lib and daemon write struct on unix domain socket for communication
|
||||
*/
|
||||
|
||||
#define JAY_TODO_CONTEXT 0
|
||||
#define JAY_TODO_WIDE 1
|
||||
|
||||
#define PCSC_STANDIN 1
|
||||
|
||||
#include "chansrv.h"
|
||||
#include "os_calls.h"
|
||||
#include "smartcard.h"
|
||||
#include "log.h"
|
||||
#include "irp.h"
|
||||
#include "devredir.h"
|
||||
#include "trans.h"
|
||||
#include "chansrv.h"
|
||||
|
||||
#if PCSC_STANDIN
|
||||
|
||||
/* module based logging */
|
||||
#define LOG_ERROR 0
|
||||
#define LOG_INFO 1
|
||||
#define LOG_DEBUG 2
|
||||
#define LOG_LEVEL LOG_ERROR
|
||||
#define LLOG_LEVEL 11
|
||||
#define LLOGLN(_level, _args) \
|
||||
do \
|
||||
{ \
|
||||
if (_level < LLOG_LEVEL) \
|
||||
{ \
|
||||
g_write("chansrv:smartcard_pcsc [%10.10u]: ", g_time3()); \
|
||||
g_writeln _args ; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define log_error(_params...) \
|
||||
{ \
|
||||
g_write("[%10.10u]: PCSC %s: %d : ERROR: ", \
|
||||
g_time3(), __func__, __LINE__); \
|
||||
g_writeln (_params); \
|
||||
}
|
||||
#define XRDP_PCSC_STATE_NONE 0
|
||||
#define XRDP_PCSC_STATE_GOT_EC (1 << 0) /* establish context */
|
||||
#define XRDP_PCSC_STATE_GOT_LR (1 << 1) /* list readers */
|
||||
#define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */
|
||||
#define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */
|
||||
#define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */
|
||||
#define XRDP_PCSC_STATE_GOT_BT (1 << 5) /* begin transaction */
|
||||
|
||||
#define log_always(_params...) \
|
||||
{ \
|
||||
g_write("[%10.10u]: PCSC %s: %d : ALWAYS: ", \
|
||||
g_time3(), __func__, __LINE__); \
|
||||
g_writeln (_params); \
|
||||
}
|
||||
|
||||
#define log_info(_params...) \
|
||||
{ \
|
||||
if (LOG_INFO <= LOG_LEVEL) \
|
||||
{ \
|
||||
g_write("[%10.10u]: PCSC %s: %d : ", \
|
||||
g_time3(), __func__, __LINE__); \
|
||||
g_writeln (_params); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define log_debug(_params...) \
|
||||
{ \
|
||||
if (LOG_DEBUG <= LOG_LEVEL) \
|
||||
{ \
|
||||
g_write("[%10.10u]: PCSC %s: %d : ", \
|
||||
g_time3(), __func__, __LINE__); \
|
||||
g_writeln (_params); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PCSCLITE_MSG_KEY_LEN 16
|
||||
#define PCSCLITE_MAX_MESSAGE_SIZE 2048
|
||||
|
||||
struct version_struct
|
||||
{
|
||||
tsi32 major; /**< IPC major \ref PROTOCOL_VERSION_MAJOR */
|
||||
tsi32 minor; /**< IPC minor \ref PROTOCOL_VERSION_MINOR */
|
||||
tui32 rv;
|
||||
};
|
||||
typedef struct version_struct version_struct;
|
||||
|
||||
struct rxSharedSegment
|
||||
{
|
||||
tui32 mtype; /** one of the \c pcsc_adm_commands */
|
||||
tui32 user_id;
|
||||
tui32 group_id;
|
||||
tui32 command; /** one of the \c pcsc_msg_commands */
|
||||
tui64 date;
|
||||
tui8 key[PCSCLITE_MSG_KEY_LEN]; /* 16 bytes */
|
||||
union _u
|
||||
{
|
||||
tui8 data[PCSCLITE_MAX_MESSAGE_SIZE];
|
||||
struct version_struct veStr;
|
||||
} u;
|
||||
};
|
||||
typedef struct rxSharedSegment sharedSegmentMsg, *psharedSegmentMsg;
|
||||
|
||||
#define RXSHAREDSEGMENT_BYTES 2088
|
||||
/* TODO: put this in con */
|
||||
static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE;
|
||||
|
||||
extern int g_display_num; /* in chansrv.c */
|
||||
|
||||
@ -116,15 +74,14 @@ static struct pcsc_client *g_tail = 0;
|
||||
|
||||
static struct trans *g_lis = 0;
|
||||
static struct trans *g_con = 0; /* todo, remove this */
|
||||
|
||||
static char g_pcsc_directory[256] = "";
|
||||
static char g_pcsclite_ipc_dir[256] = "";
|
||||
static int g_pub_file_fd = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout)
|
||||
{
|
||||
log_debug("scard_pcsc_get_wait_objs");
|
||||
|
||||
LLOGLN(0, ("scard_pcsc_get_wait_objs"));
|
||||
if (g_lis != 0)
|
||||
{
|
||||
trans_get_wait_objs(g_lis, objs, count);
|
||||
@ -140,8 +97,7 @@ scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout)
|
||||
int APP_CC
|
||||
scard_pcsc_check_wait_objs(void)
|
||||
{
|
||||
log_debug("scard_pcsc_check_wait_objs");
|
||||
|
||||
LLOGLN(0, ("scard_pcsc_check_wait_objs"));
|
||||
if (g_lis != 0)
|
||||
{
|
||||
trans_check_wait_objs(g_lis);
|
||||
@ -156,34 +112,488 @@ scard_pcsc_check_wait_objs(void)
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_version(psharedSegmentMsg msg)
|
||||
scard_process_establish_context(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
int dwScope;
|
||||
|
||||
LLOGLN(0, ("scard_process_establish_context:"));
|
||||
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC)
|
||||
{
|
||||
LLOGLN(0, ("scard_process_establish_context: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_EC;
|
||||
in_uint32_le(in_s, dwScope);
|
||||
LLOGLN(0, ("scard_process_establish_context: dwScope 0x%8.8x", dwScope));
|
||||
scard_send_establish_context(con, dwScope);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_msg(struct stream *s)
|
||||
scard_function_establish_context_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len)
|
||||
{
|
||||
int bytes;
|
||||
tui32 context;
|
||||
tui32 context_len;
|
||||
struct stream *out_s;
|
||||
|
||||
LLOGLN(0, ("scard_function_establish_context_return:"));
|
||||
if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) == 0)
|
||||
{
|
||||
LLOGLN(0, ("scard_function_establish_context_return: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC;
|
||||
in_uint8s(in_s, 28);
|
||||
in_uint32_le(in_s, context_len);
|
||||
if (context_len != 4)
|
||||
{
|
||||
LLOGLN(0, ("scard_function_establish_context_return: opps"));
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(in_s, context);
|
||||
LLOGLN(0, ("scard_function_establish_context_return: context 0x%8.8x", context));
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
s_push_layer(out_s, iso_hdr, 8);
|
||||
out_uint32_le(out_s, context);
|
||||
out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
|
||||
s_mark_end(out_s);
|
||||
bytes = (int) (out_s->end - out_s->data);
|
||||
s_pop_layer(out_s, iso_hdr);
|
||||
out_uint32_le(out_s, bytes - 8);
|
||||
out_uint32_le(out_s, 0x01); /* SCARD_ESTABLISH_CONTEXT 0x01 */
|
||||
return trans_force_write(con);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_release_context(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
int hContext;
|
||||
|
||||
LLOGLN(0, ("scard_process_release_context:"));
|
||||
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC)
|
||||
{
|
||||
LLOGLN(0, ("scard_process_establish_context: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RC;
|
||||
in_uint32_le(in_s, hContext);
|
||||
LLOGLN(0, ("scard_process_release_context: hContext 0x%8.8x", hContext));
|
||||
scard_send_release_context(con, hContext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_function_release_context_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len)
|
||||
{
|
||||
int bytes;
|
||||
struct stream *out_s;
|
||||
tui32 context;
|
||||
|
||||
LLOGLN(0, ("scard_function_release_context_return:"));
|
||||
if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) == 0)
|
||||
{
|
||||
LLOGLN(0, ("scard_function_release_context_return: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RC;
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
s_push_layer(out_s, iso_hdr, 8);
|
||||
out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
|
||||
s_mark_end(out_s);
|
||||
bytes = (int) (out_s->end - out_s->data);
|
||||
s_pop_layer(out_s, iso_hdr);
|
||||
out_uint32_le(out_s, bytes - 8);
|
||||
out_uint32_le(out_s, 0x02); /* SCARD_RELEASE_CONTEXT 0x02 */
|
||||
return trans_force_write(con);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_list_readers(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
int hContext;
|
||||
|
||||
LLOGLN(0, ("scard_process_list_readers:"));
|
||||
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR)
|
||||
{
|
||||
LLOGLN(0, ("scard_process_list_readers: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR;
|
||||
in_uint32_le(in_s, hContext);
|
||||
LLOGLN(0, ("scard_process_list_readers: dwScope 0x%8.8x", hContext));
|
||||
scard_send_list_readers(con, hContext, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
scard_function_list_readers_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len)
|
||||
{
|
||||
struct stream *out_s;
|
||||
int chr;
|
||||
int readers;
|
||||
int rn_index;
|
||||
int index;
|
||||
int bytes;
|
||||
twchar reader_name[100];
|
||||
char lreader_name[16][100];
|
||||
|
||||
LLOGLN(10, ("scard_function_list_readers_return:"));
|
||||
g_hexdump(in_s->p, len);
|
||||
if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) == 0)
|
||||
{
|
||||
LLOGLN(10, ("scard_function_list_readers_return: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR;
|
||||
|
||||
g_memset(reader_name, 0, sizeof(reader_name));
|
||||
g_memset(lreader_name, 0, sizeof(lreader_name));
|
||||
in_uint8s(in_s, 28);
|
||||
len -= 28;
|
||||
in_uint32_le(in_s, len);
|
||||
g_writeln("len %d", len);
|
||||
rn_index = 0;
|
||||
readers = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
in_uint16_le(in_s, chr);
|
||||
len -= 2;
|
||||
if (chr == 0)
|
||||
{
|
||||
if (reader_name[0] != 0)
|
||||
{
|
||||
g_wcstombs(lreader_name[readers], reader_name, 99);
|
||||
g_writeln("1 %s", lreader_name[readers]);
|
||||
g_memset(reader_name, 0, sizeof(reader_name));
|
||||
readers++;
|
||||
}
|
||||
reader_name[0] = 0;
|
||||
rn_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
reader_name[rn_index] = chr;
|
||||
rn_index++;
|
||||
}
|
||||
}
|
||||
if (rn_index > 0)
|
||||
{
|
||||
if (reader_name[0] != 0)
|
||||
{
|
||||
g_wcstombs(lreader_name[readers], reader_name, 99);
|
||||
g_writeln("2 %s", lreader_name[readers]);
|
||||
g_memset(reader_name, 0, sizeof(reader_name));
|
||||
readers++;
|
||||
}
|
||||
}
|
||||
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
s_push_layer(out_s, iso_hdr, 8);
|
||||
out_uint32_le(out_s, readers);
|
||||
for (index = 0; index < readers; index++)
|
||||
{
|
||||
g_writeln("3 - %s", lreader_name[index]);
|
||||
out_uint8a(out_s, lreader_name[index], 100);
|
||||
}
|
||||
out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
|
||||
s_mark_end(out_s);
|
||||
bytes = (int) (out_s->end - out_s->data);
|
||||
s_pop_layer(out_s, iso_hdr);
|
||||
out_uint32_le(out_s, bytes - 8);
|
||||
out_uint32_le(out_s, 0x03); /* SCARD_LIST_READERS 0x03 */
|
||||
return trans_force_write(con);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_connect(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
int hContext;
|
||||
char szReader[100];
|
||||
READER_STATE rs;
|
||||
|
||||
LLOGLN(0, ("scard_process_connect:"));
|
||||
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C)
|
||||
{
|
||||
LLOGLN(0, ("scard_process_connect: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_memset(&rs, 0, sizeof(rs));
|
||||
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_C;
|
||||
in_uint32_le(in_s, hContext);
|
||||
in_uint8a(in_s, szReader, 100);
|
||||
in_uint32_le(in_s, rs.shared_mode_flag);
|
||||
in_uint32_le(in_s, rs.preferred_protocol);
|
||||
LLOGLN(0, ("scard_process_connect: dwShareMode 0x%8.8x "
|
||||
"dwPreferredProtocols 0x%8.8x", rs.shared_mode_flag,
|
||||
rs.preferred_protocol));
|
||||
scard_send_connect(con, hContext, 1, &rs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
scard_function_connect_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len)
|
||||
{
|
||||
int dwActiveProtocol;
|
||||
int hCard;
|
||||
int bytes;
|
||||
struct stream *out_s;
|
||||
|
||||
g_hexdump(in_s->p, len);
|
||||
if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0)
|
||||
{
|
||||
LLOGLN(0, ("scard_function_connect_return: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C;
|
||||
in_uint8s(in_s, 36);
|
||||
in_uint32_le(in_s, dwActiveProtocol);
|
||||
in_uint8s(in_s, 36);
|
||||
in_uint32_le(in_s, hCard);
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
s_push_layer(out_s, iso_hdr, 8);
|
||||
out_uint32_le(out_s, hCard);
|
||||
out_uint32_le(out_s, dwActiveProtocol);
|
||||
out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
|
||||
s_mark_end(out_s);
|
||||
bytes = (int) (out_s->end - out_s->data);
|
||||
s_pop_layer(out_s, iso_hdr);
|
||||
out_uint32_le(out_s, bytes - 8);
|
||||
out_uint32_le(out_s, 0x04); /* SCARD_CONNECT 0x04 */
|
||||
return trans_force_write(con);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_begin_transaction(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
int hCard;
|
||||
|
||||
LLOGLN(0, ("scard_process_begin_transaction:"));
|
||||
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT)
|
||||
{
|
||||
LLOGLN(0, ("scard_process_begin_transaction: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_BT;
|
||||
in_uint32_le(in_s, hCard);
|
||||
LLOGLN(0, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard));
|
||||
scard_send_begin_transaction(con, hCard);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_get_status_change(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
int index;
|
||||
int hContext;
|
||||
int dwTimeout;
|
||||
int cReaders;
|
||||
READER_STATE *rsa;
|
||||
|
||||
LLOGLN(0, ("scard_process_get_status_change:"));
|
||||
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC)
|
||||
{
|
||||
LLOGLN(0, ("scard_process_get_status_change: opps"));
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(in_s, hContext);
|
||||
in_uint32_le(in_s, dwTimeout);
|
||||
in_uint32_le(in_s, cReaders);
|
||||
if ((cReaders < 0) || (cReaders > 16))
|
||||
{
|
||||
LLOGLN(0, ("scard_process_get_status_change: bad cReaders %d", cReaders));
|
||||
return 1;
|
||||
}
|
||||
rsa = (READER_STATE *) g_malloc(sizeof(READER_STATE) * cReaders, 1);
|
||||
|
||||
for (index = 0; index < cReaders; index++)
|
||||
{
|
||||
in_uint8a(in_s, rsa[index].reader_name, 100);
|
||||
LLOGLN(10, ("scard_process_get_status_change: reader_name %s",
|
||||
rsa[index].reader_name));
|
||||
in_uint32_le(in_s, rsa[index].current_state);
|
||||
LLOGLN(10, ("scard_process_get_status_change: current_state %d",
|
||||
rsa[index].current_state));
|
||||
in_uint32_le(in_s, rsa[index].event_state);
|
||||
LLOGLN(10, ("scard_process_get_status_change: event_state %d",
|
||||
rsa[index].event_state));
|
||||
in_uint32_le(in_s, rsa[index].atr_len);
|
||||
LLOGLN(10, ("scard_process_get_status_change: atr_len %d",
|
||||
rsa[index].atr_len));
|
||||
in_uint8a(in_s, rsa[index].atr, 36);
|
||||
}
|
||||
|
||||
LLOGLN(0, ("scard_process_get_status_change: hContext 0x%8.8x dwTimeout "
|
||||
"%d cReaders %d", hContext, dwTimeout, cReaders));
|
||||
|
||||
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_GSC;
|
||||
|
||||
scard_send_get_status_change(con, hContext, 1, dwTimeout, cReaders, rsa);
|
||||
|
||||
g_free(rsa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
scard_function_get_status_change_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len)
|
||||
{
|
||||
int bytes;
|
||||
int index;
|
||||
int cReaders;
|
||||
tui32 current_state;
|
||||
tui32 event_state;
|
||||
tui32 atr_len; /* number of bytes in atr[] */
|
||||
tui8 atr[36];
|
||||
struct stream *out_s;
|
||||
|
||||
LLOGLN(0, ("scard_function_get_status_change_return:"));
|
||||
g_hexdump(in_s->p, len);
|
||||
if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC) == 0)
|
||||
{
|
||||
LLOGLN(0, ("scard_function_establish_context_return: opps"));
|
||||
return 1;
|
||||
}
|
||||
g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_GSC;
|
||||
in_uint8s(in_s, 28);
|
||||
in_uint32_le(in_s, cReaders);
|
||||
if (cReaders > 0)
|
||||
{
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
s_push_layer(out_s, iso_hdr, 8);
|
||||
out_uint32_le(out_s, cReaders);
|
||||
for (index = 0; index < cReaders; index++)
|
||||
{
|
||||
in_uint32_le(in_s, current_state);
|
||||
out_uint32_le(out_s, current_state);
|
||||
in_uint32_le(in_s, event_state);
|
||||
out_uint32_le(out_s, event_state);
|
||||
in_uint32_le(in_s, atr_len);
|
||||
out_uint32_le(out_s, atr_len);
|
||||
in_uint8a(in_s, atr, 36);
|
||||
out_uint8a(out_s, atr, 36);
|
||||
}
|
||||
out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
|
||||
s_mark_end(out_s);
|
||||
bytes = (int) (out_s->end - out_s->data);
|
||||
s_pop_layer(out_s, iso_hdr);
|
||||
out_uint32_le(out_s, bytes - 8);
|
||||
out_uint32_le(out_s, 0x0C); /* SCARD_ESTABLISH_CONTEXT 0x0C */
|
||||
return trans_force_write(con);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_msg(struct trans *con, struct stream *in_s, int command)
|
||||
{
|
||||
sharedSegmentMsg msg;
|
||||
int rv;
|
||||
|
||||
g_memset(&msg, 0, sizeof(msg));
|
||||
in_uint32_le(s, msg.mtype);
|
||||
in_uint32_le(s, msg.user_id);
|
||||
in_uint32_le(s, msg.group_id);
|
||||
in_uint32_le(s, msg.command);
|
||||
in_uint64_le(s, msg.date);
|
||||
|
||||
log_debug("scard_process_msg: mtype 0x%2.2x command 0x%2.2x",
|
||||
msg.mtype, msg.command);
|
||||
|
||||
LLOGLN(0, ("scard_process_msg: command 0x%4.4x", command));
|
||||
rv = 0;
|
||||
switch (msg.mtype)
|
||||
switch (command)
|
||||
{
|
||||
case 0xF8: /* CMD_VERSION */
|
||||
rv = scard_process_version(&msg);
|
||||
case 0x01: /* SCARD_ESTABLISH_CONTEXT */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_ESTABLISH_CONTEXT"));
|
||||
rv = scard_process_establish_context(con, in_s);
|
||||
break;
|
||||
case 0x02: /* SCARD_RELEASE_CONTEXT */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_RELEASE_CONTEXT"));
|
||||
rv = scard_process_release_context(con, in_s);
|
||||
break;
|
||||
|
||||
case 0x03: /* SCARD_LIST_READERS */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_LIST_READERS"));
|
||||
rv = scard_process_list_readers(con, in_s);
|
||||
break;
|
||||
|
||||
case 0x04: /* SCARD_CONNECT */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_CONNECT"));
|
||||
rv = scard_process_connect(con, in_s);
|
||||
break;
|
||||
|
||||
case 0x05: /* SCARD_RECONNECT */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_RECONNECT"));
|
||||
break;
|
||||
|
||||
case 0x06: /* SCARD_DISCONNECT */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_DISCONNECT"));
|
||||
break;
|
||||
|
||||
case 0x07: /* SCARD_BEGIN_TRANSACTION */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_BEGIN_TRANSACTION"));
|
||||
rv = scard_process_begin_transaction(con, in_s);
|
||||
break;
|
||||
|
||||
case 0x08: /* SCARD_END_TRANSACTION */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_END_TRANSACTION"));
|
||||
break;
|
||||
|
||||
case 0x09: /* SCARD_TRANSMIT */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_TRANSMIT"));
|
||||
break;
|
||||
|
||||
case 0x0A: /* SCARD_CONTROL */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_CONTROL"));
|
||||
break;
|
||||
|
||||
case 0x0B: /* SCARD_STATUS */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_STATUS"));
|
||||
break;
|
||||
|
||||
case 0x0C: /* SCARD_GET_STATUS_CHANGE */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_GET_STATUS_CHANGE"));
|
||||
rv = scard_process_get_status_change(con, in_s);
|
||||
break;
|
||||
|
||||
case 0x0D: /* SCARD_CANCEL */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_CANCEL"));
|
||||
break;
|
||||
|
||||
case 0x0E: /* SCARD_CANCEL_TRANSACTION */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_CANCEL_TRANSACTION"));
|
||||
break;
|
||||
|
||||
case 0x0F: /* SCARD_GET_ATTRIB */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_GET_ATTRIB"));
|
||||
break;
|
||||
|
||||
case 0x10: /* SCARD_SET_ATTRIB */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_SET_ATTRIB"));
|
||||
break;
|
||||
|
||||
default:
|
||||
LLOGLN(0, ("scard_process_msg: unknown mtype 0x%4.4x", command));
|
||||
rv = 1;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
@ -197,22 +607,27 @@ my_pcsc_trans_data_in(struct trans *trans)
|
||||
struct stream *s;
|
||||
int id;
|
||||
int size;
|
||||
int command;
|
||||
int error;
|
||||
|
||||
log_debug("my_pcsc_trans_data_in:");
|
||||
|
||||
LLOGLN(0, ("my_pcsc_trans_data_in:"));
|
||||
if (trans == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (trans != g_con)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
s = trans_get_in_s(trans);
|
||||
g_hexdump(s->p, 64);
|
||||
error = scard_process_msg(s);
|
||||
in_uint32_le(s, size);
|
||||
in_uint32_le(s, command);
|
||||
LLOGLN(0, ("my_pcsc_trans_data_in: size %d command %d", size, command));
|
||||
error = trans_force_read(trans, size);
|
||||
if (error == 0)
|
||||
{
|
||||
error = scard_process_msg(g_con, s, command);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -221,7 +636,7 @@ my_pcsc_trans_data_in(struct trans *trans)
|
||||
int DEFAULT_CC
|
||||
my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans)
|
||||
{
|
||||
log_debug("my_pcsc_trans_conn_in:");
|
||||
LLOGLN(0, ("my_pcsc_trans_conn_in:"));
|
||||
|
||||
if (trans == 0)
|
||||
{
|
||||
@ -240,11 +655,13 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans)
|
||||
|
||||
g_con = new_trans;
|
||||
g_con->trans_data_in = my_pcsc_trans_data_in;
|
||||
#if 1
|
||||
g_con->header_size = 8;
|
||||
#else
|
||||
g_con->header_size = RXSHAREDSEGMENT_BYTES;
|
||||
|
||||
log_debug("my_pcsc_trans_conn_in: sizeof sharedSegmentMsg is %d",
|
||||
sizeof(sharedSegmentMsg));
|
||||
|
||||
LLOGLN(0, ("my_pcsc_trans_conn_in: sizeof sharedSegmentMsg is %d",
|
||||
sizeof(sharedSegmentMsg)));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -253,34 +670,40 @@ int APP_CC
|
||||
scard_pcsc_init(void)
|
||||
{
|
||||
char port[256];
|
||||
char *home;
|
||||
int disp;
|
||||
int error;
|
||||
int index;
|
||||
|
||||
log_debug("scard_pcsc_init:");
|
||||
|
||||
LLOGLN(0, ("scard_pcsc_init:"));
|
||||
if (g_lis == 0)
|
||||
{
|
||||
g_lis = trans_create(TRANS_MODE_UNIX, 8192, 8192);
|
||||
g_lis->is_term = g_is_term;
|
||||
g_snprintf(g_pcsc_directory, 255, "/tmp/.xrdp/pcsc%d", g_display_num);
|
||||
if (g_directory_exist(g_pcsc_directory))
|
||||
g_lis = trans_create(2, 8192, 8192);
|
||||
|
||||
//g_snprintf(g_pcsclite_ipc_dir, 255, "/tmp/.xrdp/pcsc%d", g_display_num);
|
||||
home = g_getenv("HOME");
|
||||
disp = g_display_num;
|
||||
g_snprintf(g_pcsclite_ipc_dir, 255, "%s/.pcsc%d", home, disp);
|
||||
|
||||
if (g_directory_exist(g_pcsclite_ipc_dir))
|
||||
{
|
||||
if (g_remove_dir(g_pcsc_directory) != 0)
|
||||
if (g_remove_dir(g_pcsclite_ipc_dir) != 0)
|
||||
{
|
||||
log_error("scard_pcsc_init: g_remove_dir failed");
|
||||
LLOGLN(0, ("scard_pcsc_init: g_remove_dir failed"));
|
||||
}
|
||||
}
|
||||
if (g_create_dir(g_pcsc_directory) != 0)
|
||||
if (!g_create_dir(g_pcsclite_ipc_dir))
|
||||
{
|
||||
log_error("scard_pcsc_init: g_create_dir failed");
|
||||
LLOGLN(0, ("scard_pcsc_init: g_create_dir failed"));
|
||||
}
|
||||
g_chmod_hex(g_pcsc_directory, 0x1777);
|
||||
g_snprintf(port, 255, "%s/pcscd.comm", g_pcsc_directory);
|
||||
g_chmod_hex(g_pcsclite_ipc_dir, 0x1777);
|
||||
g_snprintf(port, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir);
|
||||
g_lis->trans_conn_in = my_pcsc_trans_conn_in;
|
||||
error = trans_listen(g_lis, port);
|
||||
if (error != 0)
|
||||
{
|
||||
log_error("scard_pcsc_init: trans_listen failed for port %s",
|
||||
port);
|
||||
LLOGLN(0, ("scard_pcsc_init: trans_listen failed for port %s",
|
||||
port));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -291,17 +714,20 @@ scard_pcsc_init(void)
|
||||
int APP_CC
|
||||
scard_pcsc_deinit(void)
|
||||
{
|
||||
log_debug("scard_pcsc_deinit:");
|
||||
|
||||
LLOGLN(0, ("scard_pcsc_deinit:"));
|
||||
if (g_lis != 0)
|
||||
{
|
||||
trans_delete(g_lis);
|
||||
g_lis = 0;
|
||||
if (g_remove_dir(g_pcsc_directory) != 0)
|
||||
|
||||
g_file_close(g_pub_file_fd);
|
||||
g_pub_file_fd = 0;
|
||||
|
||||
if (g_remove_dir(g_pcsclite_ipc_dir) != 0)
|
||||
{
|
||||
log_error("scard_pcsc_deinit: g_remove_dir failed");
|
||||
LLOGLN(0, ("scard_pcsc_deinit: g_remove_dir failed"));
|
||||
}
|
||||
g_pcsc_directory[0] = 0;
|
||||
g_pcsclite_ipc_dir[0] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,13 +24,25 @@
|
||||
#ifndef _SMARTCARD_PCSC_H
|
||||
#define _SMARTCARD_PCSC_H
|
||||
|
||||
int APP_CC
|
||||
scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout);
|
||||
int APP_CC
|
||||
scard_pcsc_check_wait_objs(void);
|
||||
int APP_CC
|
||||
scard_pcsc_init(void);
|
||||
int APP_CC
|
||||
scard_pcsc_deinit(void);
|
||||
int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout);
|
||||
int APP_CC scard_pcsc_check_wait_objs(void);
|
||||
int APP_CC scard_pcsc_init(void);
|
||||
int APP_CC scard_pcsc_deinit(void);
|
||||
int APP_CC scard_function_establish_context_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len);
|
||||
int APP_CC scard_function_release_context_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len);
|
||||
int APP_CC scard_function_list_readers_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len);
|
||||
|
||||
int APP_CC scard_function_get_status_change_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len);
|
||||
int APP_CC scard_function_connect_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len);
|
||||
|
||||
#endif /* end #ifndef _SMARTCARD_PCSC_H */
|
||||
|
@ -471,6 +471,8 @@ int
|
||||
rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv);
|
||||
int
|
||||
rdpup_remove_os_bitmap(int rdpindex);
|
||||
int
|
||||
rdpup_update_os_use(int rdpindex);
|
||||
void
|
||||
rdpup_get_screen_image_rect(struct image_data* id);
|
||||
void
|
||||
|
@ -429,6 +429,8 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
pSrcPixmap = (PixmapPtr)pSrc;
|
||||
pSrcPriv = GETPIXPRIV(pSrcPixmap);
|
||||
|
||||
LLOGLN(10, ("rdpCopyArea: 3 %d %d", pSrcPixmap->usage_hint, pSrcPriv->is_scratch));
|
||||
|
||||
if (xrdp_is_os(pSrcPixmap, pSrcPriv))
|
||||
{
|
||||
if (pDst->type == DRAWABLE_WINDOW)
|
||||
@ -468,7 +470,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(10, ("rdpCopyArea: 2"));
|
||||
LLOGLN(10, ("rdpCopyArea: 2 %d %d", pSrcPixmap->usage_hint, pSrcPriv->is_scratch));
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,7 +497,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
LLOGLN(10, ("rdpCopyArea: getting dirty"));
|
||||
pDstPriv->is_dirty = 1;
|
||||
pDirtyPriv = pDstPriv;
|
||||
dirty_type = RDI_IMGLL;
|
||||
dirty_type = RDI_IMGLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -525,7 +527,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
LLOGLN(10, ("rdpCopyArea: getting dirty"));
|
||||
g_screenPriv.is_dirty = 1;
|
||||
pDirtyPriv = &g_screenPriv;
|
||||
dirty_type = RDI_IMGLL;
|
||||
dirty_type = RDI_IMGLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -541,6 +543,8 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
return rv;
|
||||
}
|
||||
|
||||
LLOGLN(10, ("rdpCopyArea: post_process"));
|
||||
|
||||
RegionInit(&clip_reg, NullBox, 0);
|
||||
cd = rdp_get_clip(&clip_reg, pDst, pGC);
|
||||
|
||||
|
@ -108,7 +108,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
|
||||
LLOGLN(10, ("rdpPolyFillRect: getting dirty"));
|
||||
g_screenPriv.is_dirty = 1;
|
||||
pDirtyPriv = &g_screenPriv;
|
||||
dirty_type = RDI_IMGLL;
|
||||
dirty_type = (FillTiled == pGC->fillStyle) ?
|
||||
RDI_IMGLY : RDI_IMGLL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -125,7 +126,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
|
||||
LLOGLN(10, ("rdpPolyFillRect: getting dirty"));
|
||||
pDstPriv->is_dirty = 1;
|
||||
pDirtyPriv = pDstPriv;
|
||||
dirty_type = RDI_FILL;
|
||||
dirty_type = (FillTiled == pGC->fillStyle) ?
|
||||
RDI_IMGLY : RDI_IMGLL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -151,7 +153,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
|
||||
LLOGLN(10, ("rdpPolyFillRect: getting dirty"));
|
||||
g_screenPriv.is_dirty = 1;
|
||||
pDirtyPriv = &g_screenPriv;
|
||||
dirty_type = RDI_IMGLL;
|
||||
dirty_type = (FillTiled == pGC->fillStyle) ?
|
||||
RDI_IMGLY : RDI_IMGLL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -192,7 +195,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, RDI_IMGLL, 2);
|
||||
draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy,
|
||||
dirty_type, 2);
|
||||
}
|
||||
}
|
||||
else if (got_id)
|
||||
@ -214,7 +218,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
|
||||
for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--)
|
||||
{
|
||||
box = REGION_RECTS(fill_reg)[j];
|
||||
rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
|
||||
rdpup_fill_rect(box.x1, box.y1,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
}
|
||||
|
||||
rdpup_set_opcode(GXcopy);
|
||||
@ -251,13 +256,15 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
|
||||
pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */
|
||||
{
|
||||
LLOGLN(10, ("rdpPolyFillRect: 3"));
|
||||
draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel,
|
||||
draw_item_add_fill_region(pDirtyPriv, &clip_reg,
|
||||
pGC->fgPixel,
|
||||
pGC->alu);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(10, ("rdpPolyFillRect: 4"));
|
||||
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, RDI_IMGLL, 2);
|
||||
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy,
|
||||
dirty_type, 2);
|
||||
}
|
||||
}
|
||||
else if (got_id)
|
||||
@ -281,7 +288,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
|
||||
for (j = num_clips - 1; j >= 0; j--)
|
||||
{
|
||||
box = REGION_RECTS(&clip_reg)[j];
|
||||
rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
|
||||
rdpup_fill_rect(box.x1, box.y1,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
}
|
||||
|
||||
rdpup_set_opcode(GXcopy);
|
||||
@ -291,7 +299,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
|
||||
for (j = num_clips - 1; j >= 0; j--)
|
||||
{
|
||||
box = REGION_RECTS(&clip_reg)[j];
|
||||
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
|
||||
rdpup_send_area(&id, box.x1, box.y1,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
|
||||
LLOGLN(10, ("rdpPutImage: getting dirty"));
|
||||
g_screenPriv.is_dirty = 1;
|
||||
pDirtyPriv = &g_screenPriv;
|
||||
dirty_type = RDI_IMGLL;
|
||||
dirty_type = RDI_IMGLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -739,13 +739,12 @@ rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
|
||||
width, org_width, depth, g_rdpScreen.depth));
|
||||
pScreen->CreatePixmap = g_rdpScreen.CreatePixmap;
|
||||
rv = pScreen->CreatePixmap(pScreen, width, height, depth, usage_hint);
|
||||
pScreen->CreatePixmap = rdpCreatePixmap;
|
||||
priv = GETPIXPRIV(rv);
|
||||
priv->rdpindex = -1;
|
||||
priv->con_number = g_con_number;
|
||||
priv->kind_width = width;
|
||||
pScreen->ModifyPixmapHeader(rv, org_width, 0, 0, 0, 0, 0);
|
||||
pScreen->CreatePixmap = rdpCreatePixmap;
|
||||
if (org_width == 0 && height == 0)
|
||||
if ((org_width == 0) && (height == 0))
|
||||
{
|
||||
priv->is_scratch = 1;
|
||||
}
|
||||
@ -793,14 +792,19 @@ xrdp_is_os(PixmapPtr pix, rdpPixmapPtr priv)
|
||||
int height;
|
||||
struct image_data id;
|
||||
|
||||
if (!XRDP_IS_OS(priv))
|
||||
if (XRDP_IS_OS(priv))
|
||||
{
|
||||
/* update time stamp */
|
||||
rdpup_update_os_use(priv->rdpindex);
|
||||
}
|
||||
else
|
||||
{
|
||||
width = pix->drawable.width;
|
||||
height = pix->drawable.height;
|
||||
if ((pix->usage_hint == 0) &&
|
||||
(pix->drawable.depth >= g_rdpScreen.depth) &&
|
||||
(width > 0) && (height > 0) && (priv->kind_width > 0) &&
|
||||
(priv->is_scratch == 0))
|
||||
(priv->is_scratch == 0) && (priv->use_count >= 0))
|
||||
{
|
||||
LLOGLN(10, ("%d %d", priv->kind_width, pix->drawable.width));
|
||||
priv->rdpindex = rdpup_add_os_bitmap(pix, priv);
|
||||
@ -815,11 +819,15 @@ xrdp_is_os(PixmapPtr pix, rdpPixmapPtr priv)
|
||||
box.y2 = height;
|
||||
if (g_do_dirty_os)
|
||||
{
|
||||
LLOGLN(10, ("xrdp_is_os: priv->con_number %d g_con_number %d",
|
||||
priv->con_number, g_con_number));
|
||||
LLOGLN(10, ("xrdp_is_os: priv->use_count %d", priv->use_count));
|
||||
if (priv->con_number != g_con_number)
|
||||
{
|
||||
LLOGLN(10, ("xrdp_is_os: queuing invalidating all"));
|
||||
draw_item_remove_all(priv);
|
||||
RegionInit(®1, &box, 0);
|
||||
draw_item_add_img_region(priv, ®1, GXcopy, RDI_IMGLL, 16);
|
||||
draw_item_add_img_region(priv, ®1, GXcopy, RDI_IMGLY, 16);
|
||||
RegionUninit(®1);
|
||||
priv->is_dirty = 1;
|
||||
priv->con_number = g_con_number;
|
||||
@ -1204,7 +1212,7 @@ rdpClearToBackground(WindowPtr pWin, int x, int y, int w, int h,
|
||||
|
||||
if (g_do_dirty_ons)
|
||||
{
|
||||
draw_item_add_img_region(&g_screenPriv, ®, GXcopy, RDI_IMGLL, 16);
|
||||
draw_item_add_img_region(&g_screenPriv, ®, GXcopy, RDI_IMGLY, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1242,7 +1250,7 @@ rdpRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed)
|
||||
|
||||
if (g_do_dirty_ons)
|
||||
{
|
||||
draw_item_add_img_region(&g_screenPriv, ®, GXcopy, RDI_IMGLL, 16);
|
||||
draw_item_add_img_region(&g_screenPriv, ®, GXcopy, RDI_IMGLY, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1350,7 +1358,7 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
|
||||
rdpPixmapRec *pDirtyPriv;
|
||||
struct image_data id;
|
||||
|
||||
LLOGLN(10, ("rdpComposite:"));
|
||||
LLOGLN(10, ("rdpComposite: op %d width %d height %d", op, width, height));
|
||||
ps = GetPictureScreen(g_pScreen);
|
||||
ps->Composite = g_rdpScreen.Composite;
|
||||
ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc,
|
||||
@ -1407,7 +1415,7 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
|
||||
LLOGLN(10, ("rdpComposite: getting dirty"));
|
||||
g_screenPriv.is_dirty = 1;
|
||||
pDirtyPriv = &g_screenPriv;
|
||||
dirty_type = RDI_IMGLL;
|
||||
dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1424,6 +1432,8 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
|
||||
return;
|
||||
}
|
||||
|
||||
LLOGLN(10, ("rdpComposite: post_process"));
|
||||
|
||||
if (pDst->pCompositeClip != 0)
|
||||
{
|
||||
box.x1 = p->x + xDst;
|
||||
|
@ -39,6 +39,9 @@ static char *g_shmemptr = 0;
|
||||
static int g_shmem_lineBytes = 0;
|
||||
static RegionPtr g_shm_reg = 0;
|
||||
|
||||
static int g_rect_id_ack = 0;
|
||||
static int g_rect_id = 0;
|
||||
|
||||
static int g_listen_sck = 0;
|
||||
static int g_sck = 0;
|
||||
static int g_sck_closed = 0;
|
||||
@ -82,9 +85,11 @@ struct rdpup_os_bitmap
|
||||
int stamp;
|
||||
};
|
||||
|
||||
#define MAX_OS_BYTES (16 * 1024 * 1024)
|
||||
static struct rdpup_os_bitmap *g_os_bitmaps = 0;
|
||||
static int g_max_os_bitmaps = 0;
|
||||
static int g_os_bitmap_stamp = 0;
|
||||
static int g_os_bitmap_alloc_size = 0;
|
||||
|
||||
static int g_pixmap_byte_total = 0;
|
||||
static int g_pixmap_num_used = 0;
|
||||
@ -217,6 +222,7 @@ rdpup_disconnect(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
g_os_bitmap_alloc_size = 0;
|
||||
|
||||
g_max_os_bitmaps = 0;
|
||||
g_free(g_os_bitmaps);
|
||||
@ -233,6 +239,7 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
|
||||
int rv;
|
||||
int oldest;
|
||||
int oldest_index;
|
||||
int this_bytes;
|
||||
|
||||
if (!g_connected)
|
||||
{
|
||||
@ -244,6 +251,17 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
this_bytes = pixmap->devKind * pixmap->drawable.height;
|
||||
if (this_bytes > MAX_OS_BYTES)
|
||||
{
|
||||
LLOGLN(10, ("rdpup_add_os_bitmap: error, too big this_bytes %d "
|
||||
"width %d height %d", this_bytes,
|
||||
pixmap->drawable.height, pixmap->drawable.height));
|
||||
return -1;
|
||||
}
|
||||
|
||||
oldest = 0x7fffffff;
|
||||
oldest_index = -1;
|
||||
rv = -1;
|
||||
index = 0;
|
||||
|
||||
@ -260,42 +278,77 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
|
||||
rv = index;
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (rv == -1)
|
||||
{
|
||||
/* find oldest */
|
||||
oldest = 0x7fffffff;
|
||||
oldest_index = 0;
|
||||
index = 0;
|
||||
|
||||
while (index < g_max_os_bitmaps)
|
||||
else
|
||||
{
|
||||
if (g_os_bitmaps[index].stamp < oldest)
|
||||
{
|
||||
oldest = g_os_bitmaps[index].stamp;
|
||||
oldest_index = index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
LLOGLN(10, ("rdpup_add_os_bitmap: evicting old, oldest_index %d", oldest_index));
|
||||
/* evict old */
|
||||
g_os_bitmaps[oldest_index].priv->status = 0;
|
||||
g_os_bitmaps[oldest_index].priv->con_number = 0;
|
||||
/* set new */
|
||||
g_os_bitmaps[oldest_index].pixmap = pixmap;
|
||||
g_os_bitmaps[oldest_index].priv = priv;
|
||||
g_os_bitmaps[oldest_index].stamp = g_os_bitmap_stamp;
|
||||
g_os_bitmap_stamp++;
|
||||
rv = oldest_index;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (rv == -1)
|
||||
{
|
||||
if (oldest_index == -1)
|
||||
{
|
||||
LLOGLN(0, ("rdpup_add_os_bitmap: error"));
|
||||
}
|
||||
else
|
||||
{
|
||||
rdpup_remove_os_bitmap(oldest_index);
|
||||
g_os_bitmaps[index].used = 1;
|
||||
g_os_bitmaps[index].pixmap = pixmap;
|
||||
g_os_bitmaps[index].priv = priv;
|
||||
g_os_bitmaps[index].stamp = g_os_bitmap_stamp;
|
||||
g_os_bitmap_stamp++;
|
||||
g_pixmap_num_used++;
|
||||
rv = oldest_index;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0)
|
||||
{
|
||||
return rv;
|
||||
}
|
||||
|
||||
g_os_bitmap_alloc_size += this_bytes;
|
||||
LLOGLN(10, ("rdpup_add_os_bitmap: this_bytes %d g_os_bitmap_alloc_size %d",
|
||||
this_bytes, g_os_bitmap_alloc_size));
|
||||
while (g_os_bitmap_alloc_size > MAX_OS_BYTES)
|
||||
{
|
||||
LLOGLN(10, ("rdpup_add_os_bitmap: must delete g_pixmap_num_used %d",
|
||||
g_pixmap_num_used));
|
||||
/* find oldest */
|
||||
oldest = 0x7fffffff;
|
||||
oldest_index = -1;
|
||||
index = 0;
|
||||
while (index < g_max_os_bitmaps)
|
||||
{
|
||||
if (g_os_bitmaps[index].used && g_os_bitmaps[index].stamp < oldest)
|
||||
{
|
||||
oldest = g_os_bitmaps[index].stamp;
|
||||
oldest_index = index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (oldest_index == -1)
|
||||
{
|
||||
LLOGLN(0, ("rdpup_add_os_bitmap: error 1"));
|
||||
break;
|
||||
}
|
||||
if (oldest_index == rv)
|
||||
{
|
||||
LLOGLN(0, ("rdpup_add_os_bitmap: error 2"));
|
||||
break;
|
||||
}
|
||||
rdpup_remove_os_bitmap(oldest_index);
|
||||
rdpup_delete_os_surface(oldest_index);
|
||||
}
|
||||
LLOGLN(10, ("rdpup_add_os_bitmap: new bitmap index %d", rv));
|
||||
LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used));
|
||||
LLOGLN(10, ("rdpup_add_os_bitmap: g_pixmap_num_used %d "
|
||||
"g_os_bitmap_stamp 0x%8.8x", g_pixmap_num_used, g_os_bitmap_stamp));
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -303,8 +356,12 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
|
||||
int
|
||||
rdpup_remove_os_bitmap(int rdpindex)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
rdpPixmapPtr priv;
|
||||
int this_bytes;
|
||||
|
||||
LLOGLN(10, ("rdpup_remove_os_bitmap: index %d stamp %d",
|
||||
rdpindex, g_os_bitmaps[rdpindex].stamp));
|
||||
rdpindex, g_os_bitmaps[rdpindex].stamp));
|
||||
|
||||
if (g_os_bitmaps == 0)
|
||||
{
|
||||
@ -318,16 +375,66 @@ rdpup_remove_os_bitmap(int rdpindex)
|
||||
|
||||
if (g_os_bitmaps[rdpindex].used)
|
||||
{
|
||||
pixmap = g_os_bitmaps[rdpindex].pixmap;
|
||||
priv = g_os_bitmaps[rdpindex].priv;
|
||||
draw_item_remove_all(priv);
|
||||
this_bytes = pixmap->devKind * pixmap->drawable.height;
|
||||
g_os_bitmap_alloc_size -= this_bytes;
|
||||
LLOGLN(10, ("rdpup_remove_os_bitmap: this_bytes %d "
|
||||
"g_os_bitmap_alloc_size %d", this_bytes,
|
||||
g_os_bitmap_alloc_size));
|
||||
g_os_bitmaps[rdpindex].used = 0;
|
||||
g_os_bitmaps[rdpindex].pixmap = 0;
|
||||
g_os_bitmaps[rdpindex].priv = 0;
|
||||
g_pixmap_num_used--;
|
||||
priv->status = 0;
|
||||
priv->con_number = 0;
|
||||
priv->use_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(0, ("rdpup_remove_os_bitmap: error"));
|
||||
}
|
||||
|
||||
LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
rdpup_update_os_use(int rdpindex)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
rdpPixmapPtr priv;
|
||||
int this_bytes;
|
||||
|
||||
LLOGLN(10, ("rdpup_update_use: index %d stamp %d",
|
||||
rdpindex, g_os_bitmaps[rdpindex].stamp));
|
||||
|
||||
if (g_os_bitmaps == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((rdpindex < 0) && (rdpindex >= g_max_os_bitmaps))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_os_bitmaps[rdpindex].used)
|
||||
{
|
||||
g_os_bitmaps[rdpindex].stamp = g_os_bitmap_stamp;
|
||||
g_os_bitmap_stamp++;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(0, ("rdpup_update_use: error rdpindex %d", rdpindex));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int
|
||||
@ -433,7 +540,14 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
|
||||
|
||||
if (g_do_dirty_ons)
|
||||
{
|
||||
rdpup_check_dirty_screen(&g_screenPriv);
|
||||
if (g_rect_id == g_rect_id_ack)
|
||||
{
|
||||
rdpup_check_dirty_screen(&g_screenPriv);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(0, ("rdpDeferredUpdateCallback: skipping"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -909,11 +1023,13 @@ rdpup_process_msg(struct stream *s)
|
||||
{
|
||||
LLOGLN(10, ("rdpup_process_msg: got msg 105"));
|
||||
in_uint32_le(s, flags);
|
||||
in_uint32_le(s, g_rect_id_ack);
|
||||
in_uint32_le(s, x);
|
||||
in_uint32_le(s, y);
|
||||
in_uint32_le(s, cx);
|
||||
in_uint32_le(s, cy);
|
||||
LLOGLN(10, (" %d %d %d %d", x, y, cx ,cy));
|
||||
LLOGLN(10, (" rect_id %d rect_id_ack %d", g_rect_id, g_rect_id_ack));
|
||||
|
||||
box.x1 = x;
|
||||
box.y1 = y;
|
||||
@ -926,6 +1042,8 @@ rdpup_process_msg(struct stream *s)
|
||||
RegionUninit(®);
|
||||
|
||||
}
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
rdpLog("unknown message type in rdpup_process_msg %d\n", msg_type);
|
||||
@ -1870,7 +1988,7 @@ rdpup_send_area(struct image_data *id, int x, int y, int w, int h)
|
||||
d += id->shmem_lineBytes;
|
||||
ly += 1;
|
||||
}
|
||||
size = 32;
|
||||
size = 36;
|
||||
rdpup_pre_check(size);
|
||||
out_uint16_le(g_out_s, 60);
|
||||
out_uint16_le(g_out_s, size);
|
||||
@ -1880,6 +1998,8 @@ rdpup_send_area(struct image_data *id, int x, int y, int w, int h)
|
||||
out_uint16_le(g_out_s, w);
|
||||
out_uint16_le(g_out_s, h);
|
||||
out_uint32_le(g_out_s, 0);
|
||||
g_rect_id++;
|
||||
out_uint32_le(g_out_s, g_rect_id);
|
||||
out_uint32_le(g_out_s, id->shmem_id);
|
||||
out_uint32_le(g_out_s, id->shmem_offset);
|
||||
out_uint16_le(g_out_s, id->width);
|
||||
@ -2128,10 +2248,6 @@ rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec *pDirtyPriv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* update use time / count */
|
||||
g_os_bitmaps[pDirtyPriv->rdpindex].stamp = g_os_bitmap_stamp;
|
||||
g_os_bitmap_stamp++;
|
||||
|
||||
LLOGLN(10, ("rdpup_check_dirty: got dirty"));
|
||||
rdpup_switch_os_surface(pDirtyPriv->rdpindex);
|
||||
rdpup_get_pixmap_image_rect(pDirtyPixmap, &id);
|
||||
@ -2293,8 +2409,8 @@ rdpup_check_dirty_screen(rdpPixmapRec *pDirtyPriv)
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
box = REGION_RECTS(di->reg)[index];
|
||||
LLOGLN(10, (" RDI_IMGLL %d %d %d %d", box.x1, box.y1,
|
||||
box.x2, box.y2));
|
||||
LLOGLN(10, (" RDI_IMGLL x %d y %d w %d h %d", box.x1, box.y1,
|
||||
box.x2 - box.x1, box.y2 - box.y1));
|
||||
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
|
||||
box.y2 - box.y1);
|
||||
}
|
||||
|
@ -27,8 +27,8 @@
|
||||
#include "trans.h"
|
||||
#include "list.h"
|
||||
#include "libxrdpinc.h"
|
||||
#include "xrdp_types.h"
|
||||
#include "xrdp_constants.h"
|
||||
#include "xrdp_types.h"
|
||||
#include "defines.h"
|
||||
#include "os_calls.h"
|
||||
#include "ssl_calls.h"
|
||||
|
@ -33,16 +33,27 @@ xrdp_cache_create(struct xrdp_wm *owner,
|
||||
self->wm = owner;
|
||||
self->session = session;
|
||||
self->use_bitmap_comp = client_info->use_bitmap_comp;
|
||||
self->cache1_entries = client_info->cache1_entries;
|
||||
|
||||
self->cache1_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
|
||||
client_info->cache1_entries);
|
||||
self->cache1_entries = MAX(self->cache1_entries, 0);
|
||||
self->cache1_size = client_info->cache1_size;
|
||||
self->cache2_entries = client_info->cache2_entries;
|
||||
|
||||
self->cache2_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
|
||||
client_info->cache2_entries);
|
||||
self->cache2_entries = MAX(self->cache2_entries, 0);
|
||||
self->cache2_size = client_info->cache2_size;
|
||||
self->cache3_entries = client_info->cache3_entries;
|
||||
|
||||
self->cache3_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
|
||||
client_info->cache3_entries);
|
||||
self->cache3_entries = MAX(self->cache3_entries, 0);
|
||||
self->cache3_size = client_info->cache3_size;
|
||||
|
||||
self->bitmap_cache_persist_enable = client_info->bitmap_cache_persist_enable;
|
||||
self->bitmap_cache_version = client_info->bitmap_cache_version;
|
||||
self->pointer_cache_entries = client_info->pointer_cache_entries;
|
||||
self->xrdp_os_del_list = list_create();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -2439,7 +2439,7 @@ server_switch_os_surface(struct xrdp_mod *mod, int rdpindex)
|
||||
|
||||
bi = xrdp_cache_get_os_bitmap(wm->cache, rdpindex);
|
||||
|
||||
if (bi != 0)
|
||||
if ((bi != 0) && (bi->bitmap != 0))
|
||||
{
|
||||
//g_writeln("server_switch_os_surface: setting target_surface to rdpid %d", id);
|
||||
wm->target_surface = bi->bitmap;
|
||||
|
@ -203,6 +203,9 @@ xrdp_process_main_loop(struct xrdp_process *self)
|
||||
else
|
||||
{
|
||||
g_writeln("xrdp_process_main_loop: libxrdp_process_incomming failed");
|
||||
/* this will try to send a disconnect,
|
||||
maybe should check that connection got far enough */
|
||||
libxrdp_disconnect(self->session);
|
||||
}
|
||||
/* Run end in module */
|
||||
xrdp_process_mod_end(self);
|
||||
|
@ -195,7 +195,8 @@ struct xrdp_cache
|
||||
struct xrdp_palette_item palette_items[6];
|
||||
/* bitmap */
|
||||
int bitmap_stamp;
|
||||
struct xrdp_bitmap_item bitmap_items[3][2000];
|
||||
struct xrdp_bitmap_item bitmap_items[XRDP_MAX_BITMAP_CACHE_ID]
|
||||
[XRDP_MAX_BITMAP_CACHE_IDX];
|
||||
int use_bitmap_comp;
|
||||
int cache1_entries;
|
||||
int cache1_size;
|
||||
|
@ -516,7 +516,8 @@ process_server_set_pointer_ex(struct mod *mod, struct stream *s)
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int APP_CC
|
||||
send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy)
|
||||
send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy,
|
||||
int frame_id)
|
||||
{
|
||||
int len;
|
||||
struct stream *s;
|
||||
@ -526,6 +527,7 @@ send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy)
|
||||
s_push_layer(s, iso_hdr, 4);
|
||||
out_uint16_le(s, 105);
|
||||
out_uint32_le(s, flags);
|
||||
out_uint32_le(s, frame_id);
|
||||
out_uint32_le(s, x);
|
||||
out_uint32_le(s, y);
|
||||
out_uint32_le(s, cx);
|
||||
@ -568,6 +570,7 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
|
||||
int flags;
|
||||
int shmem_id;
|
||||
int shmem_offset;
|
||||
int frame_id;
|
||||
char *bmpdata;
|
||||
char cur_data[32 * (32 * 3)];
|
||||
char cur_mask[32 * (32 / 8)];
|
||||
@ -699,6 +702,7 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
|
||||
in_uint16_le(s, cx);
|
||||
in_uint16_le(s, cy);
|
||||
in_uint32_le(s, flags);
|
||||
in_uint32_le(s, frame_id);
|
||||
in_uint32_le(s, shmem_id);
|
||||
in_uint32_le(s, shmem_offset);
|
||||
in_uint16_le(s, width);
|
||||
@ -728,7 +732,7 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
|
||||
{
|
||||
rv = 1;
|
||||
}
|
||||
send_paint_rect_ack(mod, flags, x, y, cx, cy);
|
||||
send_paint_rect_ack(mod, flags, x, y, cx, cy, frame_id);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user