Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
6040f10ca9
@ -272,19 +272,8 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataL
|
||||
xfree(format_name->name);
|
||||
}
|
||||
|
||||
if (cliprdr->format_names != NULL)
|
||||
{
|
||||
for (i = 0; i < cliprdr->num_format_names; i++)
|
||||
{
|
||||
format_name = &cliprdr->format_names[i];
|
||||
|
||||
if (format_name->length > 0)
|
||||
xfree(format_name->name);
|
||||
}
|
||||
|
||||
xfree(cliprdr->format_names);
|
||||
cliprdr->format_names = NULL;
|
||||
}
|
||||
xfree(cliprdr->format_names);
|
||||
cliprdr->format_names = NULL;
|
||||
|
||||
cliprdr->num_format_names = 0;
|
||||
|
||||
|
@ -735,6 +735,8 @@ boolean xf_authenticate(freerdp* instance, char** username, char** password, cha
|
||||
|
||||
boolean xf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
|
||||
{
|
||||
char answer;
|
||||
|
||||
printf("Certificate details:\n");
|
||||
printf("\tSubject: %s\n", subject);
|
||||
printf("\tIssuer: %s\n", issuer);
|
||||
@ -743,7 +745,6 @@ boolean xf_verify_certificate(freerdp* instance, char* subject, char* issuer, ch
|
||||
"the CA certificate in your certificate store, or the certificate has expired. "
|
||||
"Please look at the documentation on how to create local certificate store for a private CA.\n");
|
||||
|
||||
char answer;
|
||||
while (1)
|
||||
{
|
||||
printf("Do you trust the above certificate? (Y/N) ");
|
||||
@ -757,6 +758,7 @@ boolean xf_verify_certificate(freerdp* instance, char* subject, char* issuer, ch
|
||||
{
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -888,16 +890,11 @@ void xf_window_free(xfInfo* xfi)
|
||||
|
||||
if (context != NULL)
|
||||
{
|
||||
if (context->cache != NULL)
|
||||
{
|
||||
cache_free(context->cache);
|
||||
context->cache = NULL;
|
||||
}
|
||||
if (context->rail != NULL)
|
||||
{
|
||||
|
||||
rail_free(context->rail);
|
||||
context->rail = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (xfi->rfx_context)
|
||||
@ -917,8 +914,7 @@ void xf_free(xfInfo* xfi)
|
||||
{
|
||||
xf_window_free(xfi);
|
||||
|
||||
if (xfi->bmp_codec_none != NULL)
|
||||
xfree(xfi->bmp_codec_none);
|
||||
xfree(xfi->bmp_codec_none);
|
||||
|
||||
XCloseDisplay(xfi->display);
|
||||
|
||||
@ -952,7 +948,7 @@ int xfreerdp_run(freerdp* instance)
|
||||
xfi = ((xfContext*) instance->context)->xfi;
|
||||
channels = instance->context->channels;
|
||||
|
||||
while (!xfi->disconnect)
|
||||
while (!xfi->disconnect && !freerdp_shall_disconnect(instance))
|
||||
{
|
||||
rcount = 0;
|
||||
wcount = 0;
|
||||
|
@ -103,6 +103,7 @@ FREERDP_API void freerdp_context_new(freerdp* instance);
|
||||
FREERDP_API void freerdp_context_free(freerdp* instance);
|
||||
|
||||
FREERDP_API boolean freerdp_connect(freerdp* instance);
|
||||
FREERDP_API boolean freerdp_shall_disconnect(freerdp* instance);
|
||||
FREERDP_API boolean freerdp_disconnect(freerdp* instance);
|
||||
|
||||
FREERDP_API boolean freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount);
|
||||
|
@ -54,7 +54,7 @@ typedef struct rdp_input rdpInput;
|
||||
|
||||
typedef void (*pSynchronizeEvent)(rdpInput* input, uint32 flags);
|
||||
typedef void (*pKeyboardEvent)(rdpInput* input, uint16 flags, uint16 code);
|
||||
typedef void (*pUnicodeKeyboardEvent)(rdpInput* input, uint16 code);
|
||||
typedef void (*pUnicodeKeyboardEvent)(rdpInput* input, uint16 flags, uint16 code);
|
||||
typedef void (*pMouseEvent)(rdpInput* input, uint16 flags, uint16 x, uint16 y);
|
||||
typedef void (*pExtendedMouseEvent)(rdpInput* input, uint16 flags, uint16 x, uint16 y);
|
||||
|
||||
|
@ -358,7 +358,8 @@ struct rdp_settings
|
||||
rdpCertificate* server_cert; /* 269 */
|
||||
char* rdp_key_file; /* 270 */
|
||||
rdpKey* server_key; /* 271 */
|
||||
uint32 paddingL[280 - 272]; /* 272 */
|
||||
char* certificate_name; /* 272 */
|
||||
uint32 paddingL[280 - 273]; /* 273 */
|
||||
|
||||
/* Codecs */
|
||||
boolean rfx_codec; /* 280 */
|
||||
|
@ -846,8 +846,8 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, STREAM* s,
|
||||
{
|
||||
rfx_compose_message_tile(context, s,
|
||||
image_data + yIdx * 64 * rowstride + xIdx * 8 * context->bits_per_pixel,
|
||||
xIdx < numTilesX - 1 ? 64 : width - xIdx * 64,
|
||||
yIdx < numTilesY - 1 ? 64 : height - yIdx * 64,
|
||||
(xIdx < numTilesX - 1) ? 64 : width - xIdx * 64,
|
||||
(yIdx < numTilesY - 1) ? 64 : height - yIdx * 64,
|
||||
rowstride, quantVals, quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx);
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ static void rfx_encode_format_rgb(const uint8* rgb_data, int width, int height,
|
||||
|
||||
x_exceed = 64 - width;
|
||||
y_exceed = 64 - height;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = rgb_data + y * rowstride;
|
||||
@ -144,6 +145,7 @@ static void rfx_encode_format_rgb(const uint8* rgb_data, int width, int height,
|
||||
r = *(r_buf - 1);
|
||||
g = *(g_buf - 1);
|
||||
b = *(b_buf - 1);
|
||||
|
||||
for (x = 0; x < x_exceed; x++)
|
||||
{
|
||||
*r_buf++ = r;
|
||||
@ -159,6 +161,7 @@ static void rfx_encode_format_rgb(const uint8* rgb_data, int width, int height,
|
||||
r_last = r_buf - 64;
|
||||
g_last = g_buf - 64;
|
||||
b_last = b_buf - 64;
|
||||
|
||||
while (y_exceed > 0)
|
||||
{
|
||||
memcpy(r_buf, r_last, 64 * sizeof(sint16));
|
||||
@ -174,18 +177,18 @@ static void rfx_encode_format_rgb(const uint8* rgb_data, int width, int height,
|
||||
|
||||
void rfx_encode_rgb_to_ycbcr(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf)
|
||||
{
|
||||
// sint32 is used intentionally because we calculate with shifted factors!
|
||||
sint32 y, cb, cr;
|
||||
sint32 r, g, b;
|
||||
/* sint32 is used intentionally because we calculate with shifted factors! */
|
||||
int i;
|
||||
sint32 r, g, b;
|
||||
sint32 y, cb, cr;
|
||||
|
||||
/**
|
||||
* The encoded YCbCr coeffectients are represented as 11.5 fixed-point numbers:
|
||||
* The encoded YCbCr coefficients are represented as 11.5 fixed-point numbers:
|
||||
*
|
||||
* 1 sign bit + 10 integer bits + 5 fractional bits
|
||||
*
|
||||
* However only 7 integer bits will be actually used since the value range is [-128.0, 127.0].
|
||||
* In other words, the encoded coeffectients is scaled by << 5 when intepreted as sint16.
|
||||
* In other words, the encoded coefficients is scaled by << 5 when interpreted as sint16.
|
||||
* It will be scaled down to original during the quantization phase.
|
||||
*/
|
||||
for (i = 0; i < 4096; i++)
|
||||
@ -204,9 +207,9 @@ void rfx_encode_rgb_to_ycbcr(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf
|
||||
* Cr: 0.499813 << 15 = 16377, 0.418531 << 15 = 13714, 0.081282 << 15 = 2663
|
||||
*/
|
||||
|
||||
y = (r*9798 + g*19235 + b*3735)>>10;
|
||||
cb = (r*-5535 + g*-10868 + b*16403)>>10;
|
||||
cr = (r*16377 + g*-13714 + b*-2663)>>10;
|
||||
y = (r * 9798 + g * 19235 + b * 3735) >> 10;
|
||||
cb = (r * -5535 + g * -10868 + b * 16403) >> 10;
|
||||
cr = (r * 16377 + g * -13714 + b * -2663) >> 10;
|
||||
|
||||
y_r_buf[i] = MINMAX(y - 4096, -4096, 4095);
|
||||
cb_g_buf[i] = MINMAX(cb, -4096, 4095);
|
||||
|
@ -277,9 +277,16 @@ boolean rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s)
|
||||
{
|
||||
uint16 lengthSourceDescriptor;
|
||||
|
||||
stream_read_uint32(s, rdp->settings->share_id); /* shareId (4 bytes) */
|
||||
stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
|
||||
stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
|
||||
/*
|
||||
* Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain
|
||||
* the following fields.
|
||||
*/
|
||||
if (stream_get_left(s) > 0)
|
||||
{
|
||||
stream_read_uint32(s, rdp->settings->share_id); /* shareId (4 bytes) */
|
||||
stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
|
||||
stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
|
||||
}
|
||||
|
||||
rdp->state = CONNECTION_STATE_CAPABILITY;
|
||||
|
||||
@ -287,6 +294,8 @@ boolean rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s)
|
||||
{
|
||||
if (rdp_check_fds(rdp) < 0)
|
||||
return false;
|
||||
if (rdp->disconnect)
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1798,6 +1798,9 @@ boolean rdp_recv_demand_active(rdpRdp* rdp, STREAM* s)
|
||||
if (!rdp_read_header(rdp, s, &length, &channelId))
|
||||
return false;
|
||||
|
||||
if (rdp->disconnect)
|
||||
return true;
|
||||
|
||||
if (rdp->settings->encryption)
|
||||
{
|
||||
rdp_read_security_header(s, &securityFlags);
|
||||
|
@ -375,7 +375,8 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific
|
||||
return false;
|
||||
}
|
||||
stream_read_uint16(s, wSignatureBlobLen);
|
||||
if (wSignatureBlobLen != 72) {
|
||||
if (wSignatureBlobLen != 72)
|
||||
{
|
||||
printf("certificate_process_server_public_signature: invalid signature length (got %d, expected %d)\n", wSignatureBlobLen, 64);
|
||||
return false;
|
||||
}
|
||||
@ -610,13 +611,19 @@ int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificat
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
data = (char*) xmalloc(size + 1);
|
||||
length = fread(data, size, 1, fp);
|
||||
|
||||
if (size < 1)
|
||||
return match;
|
||||
|
||||
data = (char*) xmalloc(size + 2);
|
||||
|
||||
if (fread(data, size, 1, fp) != 1)
|
||||
{
|
||||
xfree(data);
|
||||
return match;
|
||||
}
|
||||
|
||||
data[size] = '\n';
|
||||
data[size + 1] = '\0';
|
||||
pline = strtok(data, "\n");
|
||||
|
||||
while (pline != NULL)
|
||||
|
@ -450,6 +450,9 @@ boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rdp->disconnect)
|
||||
return true;
|
||||
|
||||
if (!rdp_send_confirm_active(rdp))
|
||||
return false;
|
||||
|
||||
|
@ -136,7 +136,7 @@ int credssp_get_public_key(rdpCredssp* credssp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tls_verify_certificate(credssp->transport->tls, cert, credssp->transport->settings->hostname))
|
||||
if (!tls_verify_certificate(credssp->transport->tls, cert, credssp->transport->settings->hostname))
|
||||
tls_disconnect(credssp->transport->tls);
|
||||
|
||||
status = crypto_cert_get_public_key(cert, &credssp->public_key);
|
||||
|
@ -355,7 +355,7 @@ char* crypto_print_name(X509_NAME* name)
|
||||
char* buffer = NULL;
|
||||
BIO* outBIO = BIO_new(BIO_s_mem());
|
||||
|
||||
if(X509_NAME_print_ex(outBIO, name, 0, XN_FLAG_ONELINE) > 0)
|
||||
if (X509_NAME_print_ex(outBIO, name, 0, XN_FLAG_ONELINE) > 0)
|
||||
{
|
||||
unsigned long size = BIO_number_written(outBIO);
|
||||
buffer = xzalloc(size + 1);
|
||||
@ -373,6 +373,58 @@ char* crypto_cert_subject(X509* xcert)
|
||||
return crypto_print_name(X509_get_subject_name(xcert));
|
||||
}
|
||||
|
||||
char* crypto_cert_subject_common_name(X509* xcert)
|
||||
{
|
||||
int index;
|
||||
int length;
|
||||
uint8* common_name;
|
||||
X509_NAME* subject_name;
|
||||
X509_NAME_ENTRY* entry;
|
||||
ASN1_STRING* entry_data;
|
||||
|
||||
subject_name = X509_get_subject_name(xcert);
|
||||
index = X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
|
||||
|
||||
entry = X509_NAME_get_entry(subject_name, index);
|
||||
entry_data = X509_NAME_ENTRY_get_data(entry);
|
||||
|
||||
length = ASN1_STRING_to_UTF8(&common_name, entry_data);
|
||||
|
||||
return (char*) common_name;
|
||||
}
|
||||
|
||||
char** crypto_cert_subject_alt_name(X509* xcert, int* count)
|
||||
{
|
||||
int index;
|
||||
char** strings;
|
||||
uint8* string;
|
||||
int num_subject_alt_names;
|
||||
GENERAL_NAMES* subject_alt_names;
|
||||
GENERAL_NAME* subject_alt_name;
|
||||
|
||||
*count = 0;
|
||||
subject_alt_names = X509_get_ext_d2i(xcert, NID_subject_alt_name, 0, 0);
|
||||
|
||||
if (!subject_alt_names)
|
||||
return NULL;
|
||||
|
||||
num_subject_alt_names = sk_GENERAL_NAME_num(subject_alt_names);
|
||||
strings = malloc(sizeof(char*) * num_subject_alt_names);
|
||||
|
||||
for (index = 0; index < num_subject_alt_names; ++index)
|
||||
{
|
||||
subject_alt_name = sk_GENERAL_NAME_value(subject_alt_names, index);
|
||||
|
||||
if (subject_alt_name->type == GEN_DNS)
|
||||
{
|
||||
ASN1_STRING_to_UTF8(&string, subject_alt_name->d.dNSName);
|
||||
strings[(*count)++] = (char*) string;
|
||||
}
|
||||
}
|
||||
|
||||
return strings;
|
||||
}
|
||||
|
||||
char* crypto_cert_issuer(X509* xcert)
|
||||
{
|
||||
return crypto_print_name(X509_get_issuer_name(xcert));
|
||||
|
@ -115,6 +115,8 @@ typedef struct crypto_cert_struct* CryptoCert;
|
||||
CryptoCert crypto_cert_read(uint8* data, uint32 length);
|
||||
char* crypto_cert_fingerprint(X509* xcert);
|
||||
char* crypto_cert_subject(X509* xcert);
|
||||
char* crypto_cert_subject_common_name(X509* xcert);
|
||||
char** crypto_cert_subject_alt_name(X509* xcert, int* count);
|
||||
char* crypto_cert_issuer(X509* xcert);
|
||||
void crypto_cert_print_info(X509* xcert);
|
||||
void crypto_cert_free(CryptoCert cert);
|
||||
|
@ -53,7 +53,6 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
|
||||
{
|
||||
uint8 header;
|
||||
uint16 length;
|
||||
uint8 t;
|
||||
|
||||
stream_read_uint8(s, header);
|
||||
|
||||
@ -63,15 +62,7 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
|
||||
fastpath->numberEvents = (header & 0x3C) >> 2;
|
||||
}
|
||||
|
||||
stream_read_uint8(s, length); /* length1 */
|
||||
/* If most significant bit is not set, length2 is not presented. */
|
||||
if ((length & 0x80))
|
||||
{
|
||||
length &= 0x7F;
|
||||
length <<= 8;
|
||||
stream_read_uint8(s, t);
|
||||
length += t;
|
||||
}
|
||||
per_read_length(s, &length);
|
||||
|
||||
return length;
|
||||
}
|
||||
@ -394,13 +385,20 @@ static boolean fastpath_recv_input_event_sync(rdpFastPath* fastpath, STREAM* s,
|
||||
static boolean fastpath_recv_input_event_unicode(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
|
||||
{
|
||||
uint16 unicodeCode;
|
||||
uint16 flags;
|
||||
|
||||
if (stream_get_left(s) < 2)
|
||||
return false;
|
||||
|
||||
stream_read_uint16(s, unicodeCode); /* unicodeCode (2 bytes) */
|
||||
|
||||
IFCALL(fastpath->rdp->input->UnicodeKeyboardEvent, fastpath->rdp->input, unicodeCode);
|
||||
flags = 0;
|
||||
if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
|
||||
flags |= KBD_FLAGS_RELEASE;
|
||||
else
|
||||
flags |= KBD_FLAGS_DOWN;
|
||||
|
||||
IFCALL(fastpath->rdp->input->UnicodeKeyboardEvent, fastpath->rdp->input, flags, unicodeCode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -147,6 +147,12 @@ boolean freerdp_disconnect(freerdp* instance)
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean freerdp_shall_disconnect(freerdp* instance)
|
||||
{
|
||||
|
||||
return instance->context->rdp->disconnect;
|
||||
}
|
||||
|
||||
void freerdp_get_version(int* major, int* minor, int* revision)
|
||||
{
|
||||
if (major != NULL)
|
||||
|
@ -78,20 +78,32 @@ void input_send_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
rdp_send_client_input_pdu(rdp, s);
|
||||
}
|
||||
|
||||
void input_write_unicode_keyboard_event(STREAM* s, uint16 code)
|
||||
void input_write_unicode_keyboard_event(STREAM* s, uint16 flags, uint16 code)
|
||||
{
|
||||
stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */
|
||||
stream_write_uint16(s, flags); /* keyboardFlags (2 bytes) */
|
||||
stream_write_uint16(s, code); /* unicodeCode (2 bytes) */
|
||||
stream_write_uint16(s, 0); /* pad2OctetsB (2 bytes) */
|
||||
stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */
|
||||
}
|
||||
|
||||
void input_send_unicode_keyboard_event(rdpInput* input, uint16 code)
|
||||
void input_send_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
{
|
||||
STREAM* s;
|
||||
uint16 keyboardFlags = 0;
|
||||
rdpRdp* rdp = input->context->rdp;
|
||||
|
||||
/*
|
||||
* According to the specification, the slow path Unicode Keyboard Event
|
||||
* (TS_UNICODE_KEYBOARD_EVENT) contains KBD_FLAGS_RELEASE flag when key
|
||||
* is released, but contains no flags when it is pressed.
|
||||
* This is different from the slow path Keyboard Event
|
||||
* (TS_KEYBOARD_EVENT) which does contain KBD_FLAGS_DOWN flag when the
|
||||
* key is pressed.
|
||||
* There is no KBD_FLAGS_EXTENDED flag in TS_UNICODE_KEYBOARD_EVENT.
|
||||
*/
|
||||
keyboardFlags |= (flags & KBD_FLAGS_RELEASE) ? KBD_FLAGS_RELEASE : 0;
|
||||
|
||||
s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_UNICODE);
|
||||
input_write_unicode_keyboard_event(s, code);
|
||||
input_write_unicode_keyboard_event(s, flags, code);
|
||||
rdp_send_client_input_pdu(rdp, s);
|
||||
}
|
||||
|
||||
@ -152,12 +164,14 @@ void input_send_fastpath_keyboard_event(rdpInput* input, uint16 flags, uint16 co
|
||||
fastpath_send_input_pdu(rdp->fastpath, s);
|
||||
}
|
||||
|
||||
void input_send_fastpath_unicode_keyboard_event(rdpInput* input, uint16 code)
|
||||
void input_send_fastpath_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
{
|
||||
STREAM* s;
|
||||
uint8 eventFlags = 0;
|
||||
rdpRdp* rdp = input->context->rdp;
|
||||
|
||||
s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_UNICODE);
|
||||
eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0;
|
||||
s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_UNICODE);
|
||||
stream_write_uint16(s, code); /* unicodeCode (2 bytes) */
|
||||
fastpath_send_input_pdu(rdp->fastpath, s);
|
||||
}
|
||||
@ -182,6 +196,168 @@ void input_send_fastpath_extended_mouse_event(rdpInput* input, uint16 flags, uin
|
||||
fastpath_send_input_pdu(rdp->fastpath, s);
|
||||
}
|
||||
|
||||
static boolean input_recv_sync_event(rdpInput* input, STREAM* s)
|
||||
{
|
||||
uint32 toggleFlags;
|
||||
|
||||
if (stream_get_left(s) < 6)
|
||||
return false;
|
||||
|
||||
stream_seek(s, 2); /* pad2Octets (2 bytes) */
|
||||
stream_read_uint32(s, toggleFlags); /* toggleFlags (4 bytes) */
|
||||
|
||||
IFCALL(input->SynchronizeEvent, input, toggleFlags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean input_recv_keyboard_event(rdpInput* input, STREAM* s)
|
||||
{
|
||||
uint16 keyboardFlags, keyCode;
|
||||
|
||||
if (stream_get_left(s) < 6)
|
||||
return false;
|
||||
|
||||
stream_read_uint16(s, keyboardFlags); /* keyboardFlags (2 bytes) */
|
||||
stream_read_uint16(s, keyCode); /* keyCode (2 bytes) */
|
||||
stream_seek(s, 2); /* pad2Octets (2 bytes) */
|
||||
|
||||
IFCALL(input->KeyboardEvent, input, keyboardFlags, keyCode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean input_recv_unicode_keyboard_event(rdpInput* input, STREAM* s)
|
||||
{
|
||||
uint16 keyboardFlags, unicodeCode;
|
||||
|
||||
if (stream_get_left(s) < 6)
|
||||
return false;
|
||||
|
||||
stream_read_uint16(s, keyboardFlags); /* keyboardFlags (2 bytes) */
|
||||
stream_read_uint16(s, unicodeCode); /* unicodeCode (2 bytes) */
|
||||
stream_seek(s, 2); /* pad2Octets (2 bytes) */
|
||||
|
||||
/*
|
||||
* According to the specification, the slow path Unicode Keyboard Event
|
||||
* (TS_UNICODE_KEYBOARD_EVENT) contains KBD_FLAGS_RELEASE flag when key
|
||||
* is released, but contains no flags when it is pressed.
|
||||
* This is different from the slow path Keyboard Event
|
||||
* (TS_KEYBOARD_EVENT) which does contain KBD_FLAGS_DOWN flag when the
|
||||
* key is pressed.
|
||||
* Set the KBD_FLAGS_DOWN flag if the KBD_FLAGS_RELEASE flag is missing.
|
||||
*/
|
||||
|
||||
if ((keyboardFlags & KBD_FLAGS_RELEASE) == 0)
|
||||
keyboardFlags |= KBD_FLAGS_DOWN;
|
||||
|
||||
IFCALL(input->UnicodeKeyboardEvent, input, keyboardFlags, unicodeCode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean input_recv_mouse_event(rdpInput* input, STREAM* s)
|
||||
{
|
||||
uint16 pointerFlags, xPos, yPos;
|
||||
|
||||
if (stream_get_left(s) < 6)
|
||||
return false;
|
||||
|
||||
stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */
|
||||
stream_read_uint16(s, xPos); /* xPos (2 bytes) */
|
||||
stream_read_uint16(s, yPos); /* yPos (2 bytes) */
|
||||
|
||||
IFCALL(input->MouseEvent, input, pointerFlags, xPos, yPos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean input_recv_extended_mouse_event(rdpInput* input, STREAM* s)
|
||||
{
|
||||
uint16 pointerFlags, xPos, yPos;
|
||||
|
||||
if (stream_get_left(s) < 6)
|
||||
return false;
|
||||
|
||||
stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */
|
||||
stream_read_uint16(s, xPos); /* xPos (2 bytes) */
|
||||
stream_read_uint16(s, yPos); /* yPos (2 bytes) */
|
||||
|
||||
IFCALL(input->ExtendedMouseEvent, input, pointerFlags, xPos, yPos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean input_recv_event(rdpInput* input, STREAM* s)
|
||||
{
|
||||
uint16 messageType;
|
||||
|
||||
if (stream_get_left(s) < 4)
|
||||
return false;
|
||||
|
||||
stream_seek(s, 4); /* eventTime (4 bytes), ignored by the server */
|
||||
stream_read_uint16(s, messageType); /* messageType (2 bytes) */
|
||||
|
||||
switch (messageType)
|
||||
{
|
||||
case INPUT_EVENT_SYNC:
|
||||
if (!input_recv_sync_event(input, s))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_SCANCODE:
|
||||
if (!input_recv_keyboard_event(input, s))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_UNICODE:
|
||||
if (!input_recv_unicode_keyboard_event(input, s))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_MOUSE:
|
||||
if (!input_recv_mouse_event(input, s))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_MOUSEX:
|
||||
if (!input_recv_extended_mouse_event(input, s))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown messageType %u\n", messageType);
|
||||
/* Each input event uses 6 bytes. */
|
||||
stream_seek(s, 6);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean input_recv(rdpInput* input, STREAM* s)
|
||||
{
|
||||
uint16 i, numberEvents;
|
||||
|
||||
if (stream_get_left(s) < 4)
|
||||
return false;
|
||||
|
||||
stream_read_uint16(s, numberEvents); /* numberEvents (2 bytes) */
|
||||
stream_seek(s, 2); /* pad2Octets (2 bytes) */
|
||||
|
||||
/* Each input event uses 6 exactly bytes. */
|
||||
if (stream_get_left(s) < 6 * numberEvents)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < numberEvents; i++)
|
||||
{
|
||||
if (!input_recv_event(input, s))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void input_register_client_callbacks(rdpInput* input)
|
||||
{
|
||||
rdpRdp* rdp = input->context->rdp;
|
||||
@ -225,4 +401,3 @@ void input_free(rdpInput* input)
|
||||
xfree(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,16 +39,18 @@
|
||||
|
||||
void input_send_synchronize_event(rdpInput* input, uint32 flags);
|
||||
void input_send_keyboard_event(rdpInput* input, uint16 flags, uint16 code);
|
||||
void input_send_unicode_keyboard_event(rdpInput* input, uint16 code);
|
||||
void input_send_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code);
|
||||
void input_send_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y);
|
||||
void input_send_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y);
|
||||
|
||||
void input_send_fastpath_synchronize_event(rdpInput* input, uint32 flags);
|
||||
void input_send_fastpath_keyboard_event(rdpInput* input, uint16 flags, uint16 code);
|
||||
void input_send_fastpath_unicode_keyboard_event(rdpInput* input, uint16 code);
|
||||
void input_send_fastpath_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code);
|
||||
void input_send_fastpath_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y);
|
||||
void input_send_fastpath_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y);
|
||||
|
||||
boolean input_recv(rdpInput* input, STREAM* s);
|
||||
|
||||
void input_register_client_callbacks(rdpInput* input);
|
||||
|
||||
rdpInput* input_new(rdpRdp* rdp);
|
||||
|
@ -77,6 +77,11 @@ static boolean peer_recv_data_pdu(freerdp_peer* client, STREAM* s)
|
||||
return false;
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_INPUT:
|
||||
if (!input_recv(client->context->rdp->input, s))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST:
|
||||
/* TODO: notify server bitmap cache data */
|
||||
break;
|
||||
|
@ -93,12 +93,17 @@ boolean rdp_read_share_control_header(STREAM* s, uint16* length, uint16* type, u
|
||||
{
|
||||
/* Share Control Header */
|
||||
stream_read_uint16(s, *length); /* totalLength */
|
||||
|
||||
if (*length - 2 > stream_get_left(s))
|
||||
return false;
|
||||
|
||||
stream_read_uint16(s, *type); /* pduType */
|
||||
stream_read_uint16(s, *channel_id); /* pduSource */
|
||||
*type &= 0x0F; /* type is in the 4 least significant bits */
|
||||
|
||||
if (*length - 6 > stream_get_left(s))
|
||||
return false;
|
||||
if (*length > 4)
|
||||
stream_read_uint16(s, *channel_id); /* pduSource */
|
||||
else /* Windows XP can send such short DEACTIVATE_ALL PDUs. */
|
||||
*channel_id = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -229,6 +234,20 @@ boolean rdp_read_header(rdpRdp* rdp, STREAM* s, uint16* length, uint16* channel_
|
||||
MCSPDU = (rdp->settings->server_mode) ? DomainMCSPDU_SendDataRequest : DomainMCSPDU_SendDataIndication;
|
||||
mcs_read_domain_mcspdu_header(s, &MCSPDU, length);
|
||||
|
||||
if (*length - 8 > stream_get_left(s))
|
||||
return false;
|
||||
|
||||
if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum)
|
||||
{
|
||||
uint8 reason;
|
||||
|
||||
(void) per_read_enumerated(s, &reason, 0);
|
||||
|
||||
rdp->disconnect = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
|
||||
per_read_integer16(s, channel_id, 0); /* channelId */
|
||||
stream_seek(s, 1); /* dataPriority + Segmentation (0x70) */
|
||||
|
@ -155,6 +155,7 @@ struct rdp_rdp
|
||||
uint8 fips_decrypt_key[24];
|
||||
uint32 errorInfo;
|
||||
uint32 finalize_sc_pdus;
|
||||
boolean disconnect;
|
||||
};
|
||||
|
||||
void rdp_read_security_header(STREAM* s, uint16* flags);
|
||||
|
@ -185,7 +185,12 @@ int tcp_read(rdpTcp* tcp, uint8* data, int length)
|
||||
|
||||
status = recv(tcp->sockfd, data, length, 0);
|
||||
|
||||
if (status <= 0)
|
||||
if (status == 0)
|
||||
{
|
||||
/* Peer disconnected. */
|
||||
return -1;
|
||||
}
|
||||
else if (status < 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int wsa_error = WSAGetLastError();
|
||||
@ -194,17 +199,13 @@ int tcp_read(rdpTcp* tcp, uint8* data, int length)
|
||||
if (wsa_error == WSAEWOULDBLOCK)
|
||||
return 0;
|
||||
|
||||
/* When peer disconnects we get status 0 with no error. */
|
||||
if (status < 0)
|
||||
printf("recv() error: %d\n", wsa_error);
|
||||
printf("recv() error: %d\n", wsa_error);
|
||||
#else
|
||||
/* No data available */
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
return 0;
|
||||
|
||||
/* When peer disconnects we get status 0 with no error. */
|
||||
if (status < 0)
|
||||
perror("recv");
|
||||
perror("recv");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
@ -227,60 +227,114 @@ CryptoCert tls_get_certificate(rdpTls* tls)
|
||||
return cert;
|
||||
}
|
||||
|
||||
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
|
||||
boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
|
||||
{
|
||||
int match;
|
||||
boolean status;
|
||||
int index;
|
||||
char* common_name;
|
||||
char** alt_names;
|
||||
int alt_names_count;
|
||||
boolean certificate_status;
|
||||
boolean hostname_match = false;
|
||||
rdpCertificateData* certificate_data;
|
||||
|
||||
status = x509_verify_certificate(cert, tls->certificate_store->path);
|
||||
/* ignore certificate verification if user explicitly required it (discouraged) */
|
||||
if (tls->settings->ignore_certificate)
|
||||
return true; /* success! */
|
||||
|
||||
if (status != true)
|
||||
/* if user explicitly specified a certificate name, use it instead of the hostname */
|
||||
if (tls->settings->certificate_name)
|
||||
hostname = tls->settings->certificate_name;
|
||||
|
||||
/* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */
|
||||
certificate_status = x509_verify_certificate(cert, tls->certificate_store->path);
|
||||
|
||||
/* verify certificate name match */
|
||||
certificate_data = crypto_get_certificate_data(cert->px509, hostname);
|
||||
|
||||
/* extra common name and alternative names */
|
||||
common_name = crypto_cert_subject_common_name(cert->px509);
|
||||
alt_names = crypto_cert_subject_alt_name(cert->px509, &alt_names_count);
|
||||
|
||||
/* compare against common name */
|
||||
if (strcmp(hostname, common_name) == 0)
|
||||
hostname_match = true;
|
||||
|
||||
/* compare against alternative names */
|
||||
for (index = 0; index < alt_names_count; index++)
|
||||
{
|
||||
if (strcmp(hostname, alt_names[index]) == 0)
|
||||
hostname_match = true;
|
||||
}
|
||||
|
||||
/* if the certificate is valid and the certificate name matches, verification succeeds */
|
||||
if (certificate_status && hostname_match)
|
||||
return true; /* success! */
|
||||
|
||||
/* if the certificate is valid but the certificate name does not match, warn user, do not accept */
|
||||
if (certificate_status && !hostname_match)
|
||||
tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);
|
||||
|
||||
/* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */
|
||||
|
||||
if (!certificate_status)
|
||||
{
|
||||
char* issuer;
|
||||
char* subject;
|
||||
char* fingerprint;
|
||||
rdpCertificateData* certificate_data;
|
||||
|
||||
certificate_data = crypto_get_certificate_data(cert->px509, hostname);
|
||||
|
||||
match = certificate_data_match(tls->certificate_store, certificate_data);
|
||||
|
||||
if (match == 0)
|
||||
return 0;
|
||||
boolean accept_certificate = false;
|
||||
boolean verification_status = false;
|
||||
|
||||
issuer = crypto_cert_issuer(cert->px509);
|
||||
subject = crypto_cert_subject(cert->px509);
|
||||
fingerprint = crypto_cert_fingerprint(cert->px509);
|
||||
|
||||
/* search for matching entry in known_hosts file */
|
||||
match = certificate_data_match(tls->certificate_store, certificate_data);
|
||||
|
||||
if (match == 1)
|
||||
{
|
||||
boolean accept_certificate = tls->settings->ignore_certificate;
|
||||
/* no entry was found in known_hosts file, prompt user for manual verification */
|
||||
|
||||
freerdp* instance = (freerdp*) tls->settings->instance;
|
||||
|
||||
if (!hostname_match)
|
||||
tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);
|
||||
|
||||
if (instance->VerifyCertificate)
|
||||
accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint);
|
||||
|
||||
if (!accept_certificate)
|
||||
{
|
||||
freerdp* instance = (freerdp*) tls->settings->instance;
|
||||
|
||||
if (instance->VerifyCertificate)
|
||||
accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint);
|
||||
|
||||
xfree(issuer);
|
||||
xfree(subject);
|
||||
xfree(fingerprint);
|
||||
/* user did not accept, abort and do not add entry in known_hosts file */
|
||||
verification_status = false; /* failure! */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* user accepted certificate, add entry in known_hosts file */
|
||||
certificate_data_print(tls->certificate_store, certificate_data);
|
||||
verification_status = true; /* success! */
|
||||
}
|
||||
|
||||
if (!accept_certificate)
|
||||
return 1;
|
||||
|
||||
certificate_data_print(tls->certificate_store, certificate_data);
|
||||
}
|
||||
else if (match == -1)
|
||||
{
|
||||
/* entry was found in known_hosts file, but fingerprint does not match */
|
||||
tls_print_certificate_error(hostname, fingerprint);
|
||||
return 1;
|
||||
verification_status = false; /* failure! */
|
||||
}
|
||||
else if (match == 0)
|
||||
{
|
||||
verification_status = true; /* success! */
|
||||
}
|
||||
|
||||
xfree(issuer);
|
||||
xfree(subject);
|
||||
xfree(fingerprint);
|
||||
|
||||
return verification_status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void tls_print_certificate_error(char* hostname, char* fingerprint)
|
||||
@ -299,6 +353,36 @@ void tls_print_certificate_error(char* hostname, char* fingerprint)
|
||||
printf("Host key verification failed.\n");
|
||||
}
|
||||
|
||||
void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count)
|
||||
{
|
||||
int index;
|
||||
|
||||
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
printf("@ WARNING: CERTIFICATE NAME MISMATCH! @\n");
|
||||
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
printf("The hostname used for this connection (%s) \n", hostname);
|
||||
|
||||
if (alt_names_count < 1)
|
||||
{
|
||||
printf("does not match the name given in the certificate:\n");
|
||||
printf("%s\n", common_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("does not match the names given in the certificate:\n");
|
||||
printf("%s", common_name);
|
||||
|
||||
for (index = 0; index < alt_names_count; index++)
|
||||
{
|
||||
printf(", %s", alt_names[index]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("A valid certificate for the wrong name should NOT be trusted!\n");
|
||||
}
|
||||
|
||||
rdpTls* tls_new(rdpSettings* settings)
|
||||
{
|
||||
rdpTls* tls;
|
||||
|
@ -48,8 +48,9 @@ int tls_read(rdpTls* tls, uint8* data, int length);
|
||||
int tls_write(rdpTls* tls, uint8* data, int length);
|
||||
|
||||
CryptoCert tls_get_certificate(rdpTls* tls);
|
||||
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
|
||||
void tls_print_certificate_error();
|
||||
boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
|
||||
void tls_print_certificate_error(char* hostname, char* fingerprint);
|
||||
void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
|
||||
|
||||
boolean tls_print_error(char* func, SSL* connection, int value);
|
||||
|
||||
|
@ -306,6 +306,17 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
||||
{
|
||||
settings->ignore_certificate = true;
|
||||
}
|
||||
else if (strcmp("--certificate-name", argv[index]) == 0)
|
||||
{
|
||||
index++;
|
||||
if (index == argc)
|
||||
{
|
||||
printf("missing certificate name\n");
|
||||
return FREERDP_ARGS_PARSE_FAILURE;
|
||||
}
|
||||
|
||||
settings->certificate_name = xstrdup(argv[index]);
|
||||
}
|
||||
else if (strcmp("--no-fastpath", argv[index]) == 0)
|
||||
{
|
||||
settings->fastpath_input = false;
|
||||
|
@ -103,7 +103,6 @@ void* xrealloc(void* ptr, size_t size)
|
||||
|
||||
void xfree(void* ptr)
|
||||
{
|
||||
if (ptr != NULL)
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
@ -27,24 +27,28 @@ XImage* xf_snapshot(xfPeerContext* xfp, int x, int y, int width, int height)
|
||||
XImage* image;
|
||||
xfInfo* xfi = xfp->info;
|
||||
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
|
||||
if (xfi->use_xshm)
|
||||
{
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
|
||||
XCopyArea(xfi->display, xfi->root_window, xfi->fb_pixmap,
|
||||
xfi->xdamage_gc, x, y, width, height, x, y);
|
||||
|
||||
XSync(xfi->display, False);
|
||||
|
||||
image = xfi->fb_image;
|
||||
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
|
||||
image = XGetImage(xfi->display, xfi->root_window,
|
||||
x, y, width, height, AllPlanes, ZPixmap);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
@ -91,12 +95,16 @@ void* xf_frame_rate_thread(void* param)
|
||||
|
||||
void* xf_monitor_updates(void* param)
|
||||
{
|
||||
int fds;
|
||||
xfInfo* xfi;
|
||||
XEvent xevent;
|
||||
fd_set rfds_set;
|
||||
int select_status;
|
||||
int pending_events;
|
||||
xfPeerContext* xfp;
|
||||
freerdp_peer* client;
|
||||
uint32 wait_interval;
|
||||
int pending_events = 0;
|
||||
struct timeval timeout;
|
||||
int x, y, width, height;
|
||||
XDamageNotifyEvent* notify;
|
||||
xfEventRegion* event_region;
|
||||
@ -105,14 +113,32 @@ void* xf_monitor_updates(void* param)
|
||||
xfp = (xfPeerContext*) client->context;
|
||||
xfi = xfp->info;
|
||||
|
||||
fds = xfi->xfds;
|
||||
wait_interval = (1000000 / 2500);
|
||||
memset(&timeout, 0, sizeof(struct timeval));
|
||||
|
||||
pthread_create(&(xfp->frame_rate_thread), 0, xf_frame_rate_thread, (void*) client);
|
||||
|
||||
pthread_detach(pthread_self());
|
||||
|
||||
wait_interval = (1000000 / 2500);
|
||||
|
||||
while (1)
|
||||
{
|
||||
FD_ZERO(&rfds_set);
|
||||
FD_SET(fds, &rfds_set);
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = wait_interval;
|
||||
select_status = select(fds + 1, &rfds_set, NULL, NULL, &timeout);
|
||||
|
||||
if (select_status == -1)
|
||||
{
|
||||
printf("select failed\n");
|
||||
}
|
||||
else if (select_status == 0)
|
||||
{
|
||||
//printf("select timeout\n");
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
pending_events = XPending(xfi->display);
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
@ -139,8 +165,6 @@ void* xf_monitor_updates(void* param)
|
||||
xf_event_push(xfp->event_queue, (xfEvent*) event_region);
|
||||
}
|
||||
}
|
||||
|
||||
freerdp_usleep(wait_interval);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -54,9 +54,9 @@ void xf_input_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
}
|
||||
}
|
||||
|
||||
void xf_input_unicode_keyboard_event(rdpInput* input, uint16 code)
|
||||
void xf_input_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
{
|
||||
printf("Client sent a unicode keyboard event (code:0x%X)\n", code);
|
||||
printf("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code);
|
||||
}
|
||||
|
||||
void xf_input_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
|
||||
|
@ -111,13 +111,13 @@ void xf_xdamage_init(xfInfo* xfi)
|
||||
|
||||
values.subwindow_mode = IncludeInferiors;
|
||||
xfi->xdamage_gc = XCreateGC(xfi->display, xfi->root_window, GCSubwindowMode, &values);
|
||||
XSetFunction(xfi->display, xfi->xdamage_gc, GXcopy);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void xf_xshm_init(xfInfo* xfi)
|
||||
{
|
||||
xfi->use_xshm = false;
|
||||
xfi->fb_shm_info.shmid = -1;
|
||||
xfi->fb_shm_info.shmaddr = (char*) -1;
|
||||
|
||||
@ -157,8 +157,6 @@ void xf_xshm_init(xfInfo* xfi)
|
||||
xfi->fb_pixmap = XShmCreatePixmap(xfi->display,
|
||||
xfi->root_window, xfi->fb_image->data, &(xfi->fb_shm_info),
|
||||
xfi->fb_image->width, xfi->fb_image->height, xfi->fb_image->depth);
|
||||
|
||||
//xfi->use_xshm = true;
|
||||
}
|
||||
|
||||
xfInfo* xf_info_init()
|
||||
@ -175,6 +173,7 @@ xfInfo* xf_info_init()
|
||||
|
||||
xfi = xnew(xfInfo);
|
||||
|
||||
//xfi->use_xshm = true;
|
||||
xfi->display = XOpenDisplay(NULL);
|
||||
|
||||
XInitThreads();
|
||||
@ -185,6 +184,7 @@ xfInfo* xf_info_init()
|
||||
exit(1);
|
||||
}
|
||||
|
||||
xfi->xfds = ConnectionNumber(xfi->display);
|
||||
xfi->number = DefaultScreen(xfi->display);
|
||||
xfi->screen = ScreenOfDisplay(xfi->display, xfi->number);
|
||||
xfi->depth = DefaultDepthOfScreen(xfi->screen);
|
||||
@ -393,6 +393,7 @@ void xf_peer_dump_rfx(freerdp_peer* client)
|
||||
void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int height)
|
||||
{
|
||||
STREAM* s;
|
||||
uint8* data;
|
||||
xfInfo* xfi;
|
||||
RFX_RECT rect;
|
||||
XImage* image;
|
||||
@ -412,6 +413,11 @@ void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int heigh
|
||||
|
||||
if (xfi->use_xshm)
|
||||
{
|
||||
width = x + width;
|
||||
height = y + height;
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = width;
|
||||
@ -419,8 +425,11 @@ void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int heigh
|
||||
|
||||
image = xf_snapshot(xfp, x, y, width, height);
|
||||
|
||||
rfx_compose_message(xfp->rfx_context, s, &rect, 1,
|
||||
(uint8*) image->data, xfi->width, xfi->height, image->bytes_per_line);
|
||||
data = (uint8*) image->data;
|
||||
data = &data[(y * image->bytes_per_line) + (x * image->bits_per_pixel)];
|
||||
|
||||
rfx_compose_message(xfp->rfx_context, s, &rect, 1, data,
|
||||
width, height, image->bytes_per_line);
|
||||
|
||||
cmd->destLeft = x;
|
||||
cmd->destTop = y;
|
||||
|
@ -45,6 +45,7 @@ typedef struct xf_info xfInfo;
|
||||
struct xf_info
|
||||
{
|
||||
int bpp;
|
||||
int xfds;
|
||||
int depth;
|
||||
int width;
|
||||
int height;
|
||||
|
@ -493,9 +493,9 @@ void tf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
}
|
||||
}
|
||||
|
||||
void tf_peer_unicode_keyboard_event(rdpInput* input, uint16 code)
|
||||
void tf_peer_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
{
|
||||
printf("Client sent a unicode keyboard event (code:0x%X)\n", code);
|
||||
printf("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code);
|
||||
}
|
||||
|
||||
void tf_peer_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
|
||||
|
Loading…
Reference in New Issue
Block a user