diff --git a/vnc/Makefile b/vnc/Makefile new file mode 100644 index 00000000..e7f8430f --- /dev/null +++ b/vnc/Makefile @@ -0,0 +1,14 @@ + +VNCOBJ = os_calls.o vnc.o d3des.o vncauth.o +CFLAGS = -Wall -O2 +LDFLAGS = -shared +LIBS = -ldl +CC = gcc + +all: vnc + +vnc: $(VNCOBJ) + $(CC) $(LDFLAGS) -o libvnc.so $(VNCOBJ) $(LIBS) + +clean: + rm -f *.o libvnc.so diff --git a/vnc/d3des.c b/vnc/d3des.c new file mode 100644 index 00000000..21362ad7 --- /dev/null +++ b/vnc/d3des.c @@ -0,0 +1,442 @@ +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. Also the bytebit[] array + * has been reversed so that the most significant bit in each byte of the + * key is ignored, not the least significant. + * + * These changes are: + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* D3DES (V5.09) - + * + * A portable, public domain, version of the Data Encryption Standard. + * + * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. + * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation + * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis + * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, + * for humouring me on. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. + * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. + */ + +#include "d3des.h" + +static void scrunch(unsigned char *, unsigned long *); +static void unscrun(unsigned long *, unsigned char *); +static void desfunc(unsigned long *, unsigned long *); +static void cookey(unsigned long *); + +static unsigned long KnL[32] = { 0L }; +/* +static unsigned long KnR[32] = { 0L }; +static unsigned long Kn3[32] = { 0L }; +static unsigned char Df_Key[24] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; +*/ + +static unsigned short bytebit[8] = { + 01, 02, 04, 010, 020, 040, 0100, 0200 }; + +static unsigned long bigbyte[24] = { + 0x800000L, 0x400000L, 0x200000L, 0x100000L, + 0x80000L, 0x40000L, 0x20000L, 0x10000L, + 0x8000L, 0x4000L, 0x2000L, 0x1000L, + 0x800L, 0x400L, 0x200L, 0x100L, + 0x80L, 0x40L, 0x20L, 0x10L, + 0x8L, 0x4L, 0x2L, 0x1L }; + +/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ + +static unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; + +static unsigned char totrot[16] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; + +static unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; + +void rfbDesKey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ +unsigned char *key; +int edf; +{ + register int i, j, l, m, n; + unsigned char pc1m[56], pcr[56]; + unsigned long kn[32]; + + for ( j = 0; j < 56; j++ ) { + l = pc1[j]; + m = l & 07; + pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; + } + for( i = 0; i < 16; i++ ) { + if( edf == DE1 ) m = (15 - i) << 1; + else m = i << 1; + n = m + 1; + kn[m] = kn[n] = 0L; + for( j = 0; j < 28; j++ ) { + l = j + totrot[i]; + if( l < 28 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 28; j < 56; j++ ) { + l = j + totrot[i]; + if( l < 56 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 0; j < 24; j++ ) { + if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; + if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; + } + } + cookey(kn); + return; + } + +static void cookey(raw1) +register unsigned long *raw1; +{ + register unsigned long *cook, *raw0; + unsigned long dough[32]; + register int i; + + cook = dough; + for( i = 0; i < 16; i++, raw1++ ) { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + rfbUseKey(dough); + return; + } + +void rfbCPKey(into) +register unsigned long *into; +{ + register unsigned long *from, *endp; + + from = KnL, endp = &KnL[32]; + while( from < endp ) *into++ = *from++; + return; + } + +void rfbUseKey(from) +register unsigned long *from; +{ + register unsigned long *to, *endp; + + to = KnL, endp = &KnL[32]; + while( to < endp ) *to++ = *from++; + return; + } + +void rfbDes(inblock, outblock) +unsigned char *inblock, *outblock; +{ + unsigned long work[2]; + + scrunch(inblock, work); + desfunc(work, KnL); + unscrun(work, outblock); + return; + } + +static void scrunch(outof, into) +register unsigned char *outof; +register unsigned long *into; +{ + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into++ |= (*outof++ & 0xffL); + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into |= (*outof & 0xffL); + return; + } + +static void unscrun(outof, into) +register unsigned long *outof; +register unsigned char *into; +{ + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into++ = (unsigned char)( *outof++ & 0xffL); + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into = (unsigned char)( *outof & 0xffL); + return; + } + +static unsigned long SP1[64] = { + 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, + 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, + 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, + 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, + 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, + 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, + 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, + 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, + 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, + 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, + 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, + 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, + 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, + 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; + +static unsigned long SP2[64] = { + 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, + 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, + 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, + 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, + 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, + 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, + 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, + 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, + 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, + 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, + 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, + 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, + 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, + 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, + 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, + 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; + +static unsigned long SP3[64] = { + 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, + 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, + 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, + 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, + 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, + 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, + 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, + 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, + 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, + 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, + 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, + 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, + 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, + 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, + 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, + 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; + +static unsigned long SP4[64] = { + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, + 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, + 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, + 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, + 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, + 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, + 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, + 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, + 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; + +static unsigned long SP5[64] = { + 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, + 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, + 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, + 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, + 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, + 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, + 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, + 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, + 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, + 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, + 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, + 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, + 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, + 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, + 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, + 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; + +static unsigned long SP6[64] = { + 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, + 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, + 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, + 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, + 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, + 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, + 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, + 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, + 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, + 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, + 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, + 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, + 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, + 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; + +static unsigned long SP7[64] = { + 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, + 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, + 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, + 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, + 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, + 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, + 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, + 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, + 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, + 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, + 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, + 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, + 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, + 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, + 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, + 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; + +static unsigned long SP8[64] = { + 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, + 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, + 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, + 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, + 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, + 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, + 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, + 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, + 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, + 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, + 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, + 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, + 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, + 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, + 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, + 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; + +static void desfunc(block, keys) +register unsigned long *block, *keys; +{ + register unsigned long fval, work, right, leftt; + register int round; + + leftt = block[0]; + right = block[1]; + work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; + right ^= work; + leftt ^= (work << 4); + work = ((leftt >> 16) ^ right) & 0x0000ffffL; + right ^= work; + leftt ^= (work << 16); + work = ((right >> 2) ^ leftt) & 0x33333333L; + leftt ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ leftt) & 0x00ff00ffL; + leftt ^= work; + right ^= (work << 8); + right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; + + for( round = 0; round < 8; round++ ) { + work = (right << 28) | (right >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + leftt ^= fval; + work = (leftt << 28) | (leftt >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + right ^= fval; + } + + right = (right << 31) | (right >> 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = (leftt << 31) | (leftt >> 1); + work = ((leftt >> 8) ^ right) & 0x00ff00ffL; + right ^= work; + leftt ^= (work << 8); + work = ((leftt >> 2) ^ right) & 0x33333333L; + right ^= work; + leftt ^= (work << 2); + work = ((right >> 16) ^ leftt) & 0x0000ffffL; + leftt ^= work; + right ^= (work << 16); + work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; + leftt ^= work; + right ^= (work << 4); + *block++ = right; + *block = leftt; + return; + } + +/* Validation sets: + * + * Single-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef + * Plain : 0123 4567 89ab cde7 + * Cipher : c957 4425 6a5e d31d + * + * Double-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cde7 + * Cipher : 7f1d 0a77 826b 8aff + * + * Double-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 + * + * Triple-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cde7 + * Cipher : de0b 7c06 ae5e 0ed5 + * + * Triple-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 + * + * d3des V5.0a rwo 9208.07 18:44 Graven Imagery + **********************************************************************/ diff --git a/vnc/d3des.h b/vnc/d3des.h new file mode 100644 index 00000000..e3761ca2 --- /dev/null +++ b/vnc/d3des.h @@ -0,0 +1,56 @@ +#ifndef D3DES_H +#define D3DES_H + +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. + * + * These changes are: + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* d3des.h - + * + * Headers and defines for d3des.c + * Graven Imagery, 1992. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge + * (GEnie : OUTER; CIS : [71755,204]) + */ + +#define EN0 0 /* MODE == encrypt */ +#define DE1 1 /* MODE == decrypt */ + +extern void rfbDesKey(unsigned char *, int); +/* hexkey[8] MODE + * Sets the internal key register according to the hexadecimal + * key contained in the 8 bytes of hexkey, according to the DES, + * for encryption or decryption according to MODE. + */ + +extern void rfbUseKey(unsigned long *); +/* cookedkey[32] + * Loads the internal key register with the data in cookedkey. + */ + +extern void rfbCPKey(unsigned long *); +/* cookedkey[32] + * Copies the contents of the internal key register into the storage + * located at &cookedkey[0]. + */ + +extern void rfbDes(unsigned char *, unsigned char *); +/* from[8] to[8] + * Encrypts/Decrypts (according to the key currently loaded in the + * internal key register) one block of eight bytes at address 'from' + * into the block at address 'to'. They can be the same. + */ + +/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery + ********************************************************************/ + +#endif diff --git a/vnc/os_calls.c b/vnc/os_calls.c new file mode 100644 index 00000000..c8668749 --- /dev/null +++ b/vnc/os_calls.c @@ -0,0 +1,794 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2004 + + generic operating system calls + +*/ + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define MEMLEAK + +#ifdef _WIN32 +static CRITICAL_SECTION g_term_mutex; +#else +static pthread_mutex_t g_term_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif +static int g_term = 0; + +#ifdef MEMLEAK +#include "xrdp.h" +#endif + +#ifdef MEMLEAK +static int g_memsize = 0; +static int g_memid = 0; +static struct xrdp_list* g_memlist = 0; +#endif + +/*****************************************************************************/ +int g_init_system(void) +{ +#ifdef _WIN32 + WSADATA w; + + WSAStartup(2, &w); + InitializeCriticalSection(&g_term_mutex); +#endif +#ifdef MEMLEAK + g_memlist = xrdp_list_create(); +#endif + return 0; +} + +/*****************************************************************************/ +int g_exit_system(void) +{ +#ifdef _WIN32 + WSACleanup(); + DeleteCriticalSection(&g_term_mutex); +#endif +#ifdef MEMLEAK + int i; + struct xrdp_mem* p; + + for (i = 0; i < g_memlist->count; i++) + { + p = (struct xrdp_mem*)xrdp_list_get_item(g_memlist, i); + g_printf("leak size %d id %d\n\r", p->size, p->id); + } + g_printf("mem %d\n\r", g_memsize); + xrdp_list_delete(g_memlist); + g_memlist = 0; +#endif + return 0; +} + +/*****************************************************************************/ +void* g_malloc(int size, int zero) +{ +#ifdef MEMLEAK + char* rv; + struct xrdp_mem* p; + + rv = (char*)malloc(size + sizeof(struct xrdp_mem)); + if (zero) + memset(rv, 0, size + sizeof(struct xrdp_mem)); + g_memsize += size; + p = (struct xrdp_mem*)rv; + p->size = size; + p->id = g_memid; + if (g_memlist != 0) + xrdp_list_add_item(g_memlist, (int)p); + g_memid++; + return rv + sizeof(struct xrdp_mem); +#else + char* rv; + + rv = (char*)malloc(size); + if (zero) + memset(rv, 0, size); + return rv; +#endif +} + +/*****************************************************************************/ +void* g_malloc1(int size, int zero) +{ + char* rv; + + rv = (char*)malloc(size); + if (zero) + memset(rv, 0, size); + return rv; +} + +/*****************************************************************************/ +void g_free(void* ptr) +{ +#ifdef MEMLEAK + struct xrdp_mem* p; + int i; + + if (ptr != 0) + { + p = (struct xrdp_mem*)(((char*)ptr) - sizeof(struct xrdp_mem)); + g_memsize -= p->size; + i = xrdp_list_index_of(g_memlist, (int)p); + if (i >= 0) + xrdp_list_remove_item(g_memlist, i); + free(p); + } +#else + if (ptr != 0) + { + free(ptr); + } +#endif +} + +/*****************************************************************************/ +void g_free1(void* ptr) +{ + if (ptr != 0) + { + free(ptr); + } +} + +/*****************************************************************************/ +void g_sleep(int msecs) +{ +#ifdef _WIN32 + Sleep(msecs); +#else + usleep(msecs * 1000); +#endif +} + +/*****************************************************************************/ +void g_printf(char* format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +/*****************************************************************************/ +/* produce a hex dump */ +void g_hexdump(char* p, int len) +{ + unsigned char* line; + int i; + int thisline; + int offset; + + line = (unsigned char*)p; + offset = 0; + while (offset < len) + { + printf("%04x ", offset); + thisline = len - offset; + if (thisline > 16) + thisline = 16; + for (i = 0; i < thisline; i++) + printf("%02x ", line[i]); + for (; i < 16; i++) + printf(" "); + for (i = 0; i < thisline; i++) + printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + printf("\n"); + offset += thisline; + line += thisline; + } +} + +/*****************************************************************************/ +void g_memset(void* ptr, int val, int size) +{ + memset(ptr, val, size); +} + +/*****************************************************************************/ +void g_memcpy(void* d_ptr, const void* s_ptr, int size) +{ + memcpy(d_ptr, s_ptr, size); +} + +/*****************************************************************************/ +int g_getchar(void) +{ + return getchar(); +} + +/*****************************************************************************/ +int g_tcp_socket(void) +{ + int rv; + int i; + + i = 1; + rv = socket(PF_INET, SOCK_STREAM, 0); + setsockopt(rv, IPPROTO_TCP, TCP_NODELAY, (void*)&i, sizeof(i)); + return rv; +} + +/*****************************************************************************/ +int g_tcp_local_socket(void) +{ + int rv; + + rv = socket(PF_LOCAL, SOCK_STREAM, 0); + return rv; +} + +/*****************************************************************************/ +void g_tcp_close(int sck) +{ +#ifdef _WIN32 + closesocket(sck); +#else + close(sck); +#endif +} + +/*****************************************************************************/ +int g_tcp_connect(int sck, char* address, char* port) +{ + struct sockaddr_in s; + struct hostent* h; + + g_memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons(atoi(port)); + s.sin_addr.s_addr = inet_addr(address); + if (s.sin_addr.s_addr == INADDR_NONE) + { + h = gethostbyname(address); + if (h != 0) + if (h->h_name != 0) + if (h->h_addr_list != 0) + if ((*(h->h_addr_list)) != 0) + s.sin_addr.s_addr = *((int*)(*(h->h_addr_list))); + } + return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + +/*****************************************************************************/ +int g_tcp_set_non_blocking(int sck) +{ + unsigned long i; + +#ifdef _WIN32 + i = 1; + ioctlsocket(sck, FIONBIO, &i); +#else + i = fcntl(sck, F_GETFL); + i = i | O_NONBLOCK; + fcntl(sck, F_SETFL, i); +#endif + return 0; +} + +/*****************************************************************************/ +int g_tcp_bind(int sck, char* port) +{ + struct sockaddr_in s; + + memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons(atoi(port)); + s.sin_addr.s_addr = INADDR_ANY; + return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + +/*****************************************************************************/ +int g_tcp_local_bind(int sck, char* port) +{ + struct sockaddr_un s; + + memset(&s, 0, sizeof(struct sockaddr_un)); + s.sun_family = AF_UNIX; + strcpy(s.sun_path, port); + return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_un)); +} + +/*****************************************************************************/ +int g_tcp_listen(int sck) +{ + return listen(sck, 2); +} + +/*****************************************************************************/ +int g_tcp_accept(int sck) +{ + struct sockaddr_in s; +#ifdef _WIN32 + signed int i; +#else + unsigned int i; +#endif + + i = sizeof(struct sockaddr_in); + memset(&s, 0, i); + return accept(sck, (struct sockaddr*)&s, &i); +} + +/*****************************************************************************/ +int g_tcp_last_error_would_block(int sck) +{ +#ifdef _WIN32 + return WSAGetLastError() == WSAEWOULDBLOCK; +#else + return errno == EWOULDBLOCK; +#endif +} + +/*****************************************************************************/ +int g_tcp_recv(int sck, void* ptr, int len, int flags) +{ + return recv(sck, ptr, len, flags); +} + +/*****************************************************************************/ +int g_tcp_force_recv(int sck, char* data, int len) +{ + int rcvd; + + while (len > 0) + { + rcvd = g_tcp_recv(sck, data, len, 0); + if (rcvd == -1) + { + if (g_tcp_last_error_would_block(sck)) + g_sleep(1); + else + return 1; + } + else if (rcvd == 0) + return 1; + else + { + data += rcvd; + len -= rcvd; + } + } + return 0; +} + +/*****************************************************************************/ +int g_tcp_send(int sck, void* ptr, int len, int flags) +{ + return send(sck, ptr, len, flags); +} + +/*****************************************************************************/ +int g_tcp_force_send(int sck, char* data, int len) +{ + int sent; + + while (len > 0) + { + sent = g_tcp_send(sck, data, len, 0); + if (sent == -1) + { + if (g_tcp_last_error_would_block(sck)) + g_sleep(1); + else + return 1; + } + else if (sent == 0) + return 1; + else + { + data += sent; + len -= sent; + } + } + return 0; +} + +/*****************************************************************************/ +int g_tcp_select(int sck1, int sck2) +{ + fd_set rfds; + struct timeval time; + int max; + + time.tv_sec = 0; + time.tv_usec = 0; + FD_ZERO(&rfds); + FD_SET(((unsigned int)sck1), &rfds); + FD_SET(((unsigned int)sck2), &rfds); + max = sck1; + if (sck2 > max) + max = sck2; + return select(max + 1, &rfds, 0, 0, &time); +} + +/*****************************************************************************/ +int g_is_term(void) +{ + int rv; + +#ifdef _WIN32 + EnterCriticalSection(&g_term_mutex); + rv = g_term; + LeaveCriticalSection(&g_term_mutex); +#else + pthread_mutex_lock(&g_term_mutex); + rv = g_term; + pthread_mutex_unlock(&g_term_mutex); +#endif + return rv; +} + +/*****************************************************************************/ +void g_set_term(int in_val) +{ +#ifdef _WIN32 + EnterCriticalSection(&g_term_mutex); + g_term = in_val; + LeaveCriticalSection(&g_term_mutex); +#else + pthread_mutex_lock(&g_term_mutex); + g_term = in_val; + pthread_mutex_unlock(&g_term_mutex); +#endif +} + +/*****************************************************************************/ +#ifdef _WIN32 +int g_thread_create(unsigned long (__stdcall * start_routine)(void*), void* arg) +{ + DWORD thread; + + return !CreateThread(0, 0, start_routine, arg, 0, &thread); +} +#else +int g_thread_create(void* (* start_routine)(void*), void* arg) +{ + pthread_t thread; + + return pthread_create(&thread, 0, start_routine, arg); +} +#endif + +/* rc4 stuff */ + +/*****************************************************************************/ +void* g_rc4_info_create(void) +{ + return g_malloc(sizeof(RC4_KEY), 1);; +} + +/*****************************************************************************/ +void g_rc4_info_delete(void* rc4_info) +{ + g_free(rc4_info); +} + +/*****************************************************************************/ +void g_rc4_set_key(void* rc4_info, char* key, int len) +{ + RC4_set_key((RC4_KEY*)rc4_info, len, (unsigned char*)key); +} + +/*****************************************************************************/ +void g_rc4_crypt(void* rc4_info, char* data, int len) +{ + RC4((RC4_KEY*)rc4_info, len, (unsigned char*)data, (unsigned char*)data); +} + +/* sha1 stuff */ + +/*****************************************************************************/ +void* g_sha1_info_create(void) +{ + return g_malloc(sizeof(SHA_CTX), 1); +} + +/*****************************************************************************/ +void g_sha1_info_delete(void* sha1_info) +{ + g_free(sha1_info); +} + +/*****************************************************************************/ +void g_sha1_clear(void* sha1_info) +{ + SHA1_Init((SHA_CTX*)sha1_info); +} + +/*****************************************************************************/ +void g_sha1_transform(void* sha1_info, char* data, int len) +{ + SHA1_Update((SHA_CTX*)sha1_info, data, len); +} + +/*****************************************************************************/ +void g_sha1_complete(void* sha1_info, char* data) +{ + SHA1_Final((unsigned char*)data, (SHA_CTX*)sha1_info); +} + +/* md5 stuff */ + +/*****************************************************************************/ +void* g_md5_info_create(void) +{ + return g_malloc(sizeof(MD5_CTX), 1); +} + +/*****************************************************************************/ +void g_md5_info_delete(void* md5_info) +{ + g_free(md5_info); +} + +/*****************************************************************************/ +void g_md5_clear(void* md5_info) +{ + MD5_Init((MD5_CTX*)md5_info); +} + +/*****************************************************************************/ +void g_md5_transform(void* md5_info, char* data, int len) +{ + MD5_Update((MD5_CTX*)md5_info, data, len); +} + +/*****************************************************************************/ +void g_md5_complete(void* md5_info, char* data) +{ + MD5_Final((unsigned char*)data, (MD5_CTX*)md5_info); +} + +/*****************************************************************************/ +int g_mod_exp(char* out, char* in, char* mod, char* exp) +{ + BN_CTX* ctx; + BIGNUM lmod; + BIGNUM lexp; + BIGNUM lin; + BIGNUM lout; + int rv; + + ctx = BN_CTX_new(); + BN_init(&lmod); + BN_init(&lexp); + BN_init(&lin); + BN_init(&lout); + BN_bin2bn((unsigned char*)mod, 64, &lmod); + BN_bin2bn((unsigned char*)exp, 64, &lexp); + BN_bin2bn((unsigned char*)in, 64, &lin); + BN_mod_exp(&lout, &lin, &lexp, &lmod, ctx); + rv = BN_bn2bin(&lout, (unsigned char*)out); + BN_free(&lin); + BN_free(&lout); + BN_free(&lexp); + BN_free(&lmod); + BN_CTX_free(ctx); + return rv; +} + +/*****************************************************************************/ +void g_random(char* data, int len) +{ +#ifdef _WIN32 + memset(data, 0x44, len); +#else + int fd; + + memset(data, 0x44, len); + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + fd = open("/dev/random", O_RDONLY); + if (fd != -1) + { + read(fd, data, len); + close(fd); + } +#endif +} + +/*****************************************************************************/ +int g_abs(int i) +{ + return abs(i); +} + +/*****************************************************************************/ +int g_memcmp(void* s1, void* s2, int len) +{ + return memcmp(s1, s2, len); +} + +/*****************************************************************************/ +int g_file_open(char* file_name) +{ +#ifdef _WIN32 + return (int)CreateFile(file_name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); +#else + return open(file_name, O_RDWR | O_CREAT); +#endif +} + +/*****************************************************************************/ +int g_file_close(int fd) +{ +#ifdef _WIN32 + CloseHandle((HANDLE)fd); +#else + close(fd); +#endif + return 0; +} + +/*****************************************************************************/ +/* read from file*/ +int g_file_read(int fd, char* ptr, int len) +{ +#ifdef _WIN32 + if (ReadFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) + return len; + else + return -1; +#else + return read(fd, ptr, len); +#endif +} + +/*****************************************************************************/ +/* write to file */ +int g_file_write(int fd, char* ptr, int len) +{ +#ifdef _WIN32 + if (WriteFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) + return len; + else + return -1; +#else + return write(fd, ptr, len); +#endif +} + +/*****************************************************************************/ +/* move file pointer */ +int g_file_seek(int fd, int offset) +{ +#ifdef _WIN32 + return SetFilePointer((HANDLE)fd, offset, 0, FILE_BEGIN); +#else + return lseek(fd, offset, SEEK_SET); +#endif +} + +/*****************************************************************************/ +/* do a write lock on a file */ +/* return boolean */ +int g_file_lock(int fd, int start, int len) +{ +#ifdef _WIN32 + return LockFile((HANDLE)fd, start, 0, len, 0); +#else + struct flock lock; + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = start; + lock.l_len = len; + if (fcntl(fd, F_SETLK, &lock) == -1) + return 0; + return 1; +#endif +} + +/*****************************************************************************/ +int g_strlen(char* text) +{ + return strlen(text); +} + +/*****************************************************************************/ +char* g_strcpy(char* dest, char* src) +{ + return strcpy(dest, src); +} + +/*****************************************************************************/ +char* g_strncpy(char* dest, char* src, int len) +{ + char* rv; + + rv = strncpy(dest, src, len); + dest[len] = 0; + return rv; +} + +/*****************************************************************************/ +char* g_strcat(char* dest, char* src) +{ + return strcat(dest, src); +} + +/*****************************************************************************/ +char* g_strdup(char* in) +{ + int len; + char* p; + + if (in == 0) + return 0; + len = g_strlen(in); + p = (char*)g_malloc(len + 1, 0); + g_strcpy(p, in); + return p; +} + +/*****************************************************************************/ +int g_load_library(char* in) +{ + return (int)dlopen(in, RTLD_LOCAL | RTLD_LAZY); +} + +/*****************************************************************************/ +int g_free_library(int lib) +{ + if (lib == 0) + return 0; + return dlclose((void*)lib); +} + +/*****************************************************************************/ +/* returns NULL if not found */ +void* g_get_proc_address(int lib, char* name) +{ + if (lib == 0) + return 0; + return dlsym((void*)lib, name); +} diff --git a/vnc/parse.h b/vnc/parse.h new file mode 100644 index 00000000..477f35ab --- /dev/null +++ b/vnc/parse.h @@ -0,0 +1,299 @@ +/* + rdesktop: A Remote Desktop Protocol client. + Parsing primitives + Copyright (C) Matthew Chapman 1999-2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* modified for xrdp */ +/* this is a super fast stream method, you bet */ + +#if defined L_ENDIAN +#elif defined B_ENDIAN +#else +#error Unknown endianness. +#endif + +/* parser state */ +struct stream +{ + char* p; + char* end; + char* data; + int size; + /* offsets of various headers */ + char* iso_hdr; + char* mcs_hdr; + char* sec_hdr; + char* rdp_hdr; + char* channel_hdr; + char* next_packet; +}; + +/******************************************************************************/ +#define s_check(s) (s->p <= s->end) + +/******************************************************************************/ +#define s_check_rem(s, n) (s->p + n <= s->end) + +/******************************************************************************/ +#define s_check_end(s) (s->p == s->end) + +/******************************************************************************/ +#define make_stream(s) \ +{ \ + s = (struct stream*)g_malloc(sizeof(struct stream), 1); \ +} + +/******************************************************************************/ +#define init_stream(s, v) \ +{ \ + if (v > s->size) \ + { \ + g_free(s->data); \ + s->data = (char*)g_malloc(v, 0); \ + } \ + s->p = s->data; \ + s->end = s->data; \ + s->size = v; \ + s->next_packet = 0; \ +} + +/******************************************************************************/ +#define free_stream(s) \ +{ \ + if (s != 0) \ + g_free(s->data); \ + g_free(s); \ +} \ + +/******************************************************************************/ +#define s_push_layer(s, h, n) \ +{ \ + s->h = s->p; \ + s->p += n; \ +} + +/******************************************************************************/ +#define s_pop_layer(s, h) \ +{ \ + s->p = s->h; \ +} + +/******************************************************************************/ +#define s_mark_end(s) \ +{ \ + s->end = s->p; \ +} + +/******************************************************************************/ +#define in_uint8(s, v) \ +{ \ + v = *((unsigned char*)(s->p)); \ + s->p++; \ +} + +/******************************************************************************/ +#if defined B_ENDIAN || defined NEED_ALIGN +#define in_sint16_le(s, v) \ +{ \ + v = (signed short) \ + ( \ + (*((unsigned char*)(s->p + 0)) << 0) | \ + (*((unsigned char*)(s->p + 1)) << 8) \ + ); \ + s->p += 2; \ +} +#else +#define in_sint16_le(s, v) \ +{ \ + v = *((signed short*)(s->p)); \ + s->p += 2; \ +} +#endif + +/******************************************************************************/ +#if defined B_ENDIAN || defined NEED_ALIGN +#define in_uint16_le(s, v) \ +{ \ + v = (unsigned short) \ + ( \ + (*((unsigned char*)(s->p + 0)) << 0) | \ + (*((unsigned char*)(s->p + 1)) << 8) \ + ); \ + s->p += 2; \ +} +#else +#define in_uint16_le(s, v) \ +{ \ + v = *((unsigned short*)(s->p)); \ + s->p += 2; \ +} +#endif + +/******************************************************************************/ +#define in_uint16_be(s, v) \ +{ \ + v = *((unsigned char*)(s->p)); \ + s->p++; \ + v = v << 8; \ + v = v | *((unsigned char*)(s->p)); \ + s->p++; \ +} + +/******************************************************************************/ +#if defined B_ENDIAN || defined NEED_ALIGN +#define in_uint32_le(s, v) \ +{ \ + v = (unsigned long) \ + ( \ + (*((unsigned char*)(s->p + 0)) << 0) | \ + (*((unsigned char*)(s->p + 1)) << 8) | \ + (*((unsigned char*)(s->p + 2)) << 16) | \ + (*((unsigned char*)(s->p + 3)) << 24) \ + ); \ + s->p += 4; \ +} +#else +#define in_uint32_le(s, v) \ +{ \ + v = *((unsigned long*)(s->p)); \ + s->p += 4; \ +} +#endif + +/******************************************************************************/ +#define in_uint32_be(s, v) \ +{ \ + v = *((unsigned char*)(s->p)); \ + s->p++; \ + v = v << 8; \ + v = v | *((unsigned char*)(s->p)); \ + s->p++; \ + v = v << 8; \ + v = v | *((unsigned char*)(s->p)); \ + s->p++; \ + v = v << 8; \ + v = v | *((unsigned char*)(s->p)); \ + s->p++; \ +} + +/******************************************************************************/ +#define out_uint8(s, v) \ +{ \ + *(s->p) = (unsigned char)(v); \ + s->p++; \ +} + +/******************************************************************************/ +#if defined B_ENDIAN || defined NEED_ALIGN +#define out_uint16_le(s, v) \ +{ \ + *(s->p) = (unsigned char)(v); \ + s->p++; \ + *(s->p) = (unsigned char)((v) >> 8); \ + s->p++; \ +} +#else +#define out_uint16_le(s, v) \ +{ \ + *((unsigned short*)(s->p)) = (unsigned short)(v); \ + s->p += 2; \ +} +#endif + +/******************************************************************************/ +#define out_uint16_be(s, v) \ +{ \ + *(s->p) = (unsigned char)((v) >> 8); \ + s->p++; \ + *(s->p) = (unsigned char)(v); \ + s->p++; \ +} + +/******************************************************************************/ +#if defined B_ENDIAN || defined NEED_ALIGN +#define out_uint32_le(s, v) \ +{ \ + *(s->p) = (unsigned char)(v); \ + s->p++; \ + *(s->p) = (unsigned char)((v) >> 8); \ + s->p++; \ + *(s->p) = (unsigned char)((v) >> 16); \ + s->p++; \ + *(s->p) = (unsigned char)((v) >> 24); \ + s->p++; \ +} +#else +#define out_uint32_le(s, v) \ +{ \ + *((unsigned long*)(s->p)) = (v); \ + s->p += 4; \ +} +#endif + +/******************************************************************************/ +#define out_uint32_be(s, v) \ +{ \ + *(s->p) = (unsigned char)((v) >> 24); \ + s->p++; \ + *(s->p) = (unsigned char)((v) >> 16); \ + s->p++; \ + *(s->p) = (unsigned char)((v) >> 8); \ + s->p++; \ + *(s->p) = (unsigned char)(v); \ + s->p++; \ +} + +/******************************************************************************/ +#define in_uint8p(s, v, n) \ +{ \ + v = s->p; \ + s->p += n; \ +} + +/******************************************************************************/ +#define in_uint8a(s, v, n) \ +{ \ + g_memcpy(v, s->p, n); \ + s->p += n; \ +} + +/******************************************************************************/ +#define in_uint8s(s, n) \ +{ \ + s->p += n; \ +} + +/******************************************************************************/ +#define out_uint8p(s, v, n) \ +{ \ + g_memcpy(s->p, v, n); \ + s->p += n; \ +} + +/******************************************************************************/ +#define out_uint8a(s, v, n) \ +{ \ + out_uint8p(s, v, n); \ +} + +/******************************************************************************/ +#define out_uint8s(s, n) \ +{ \ + g_memset(s->p, 0, n); \ + s->p += n; \ +} diff --git a/vnc/vnc.c b/vnc/vnc.c new file mode 100644 index 00000000..dffe0891 --- /dev/null +++ b/vnc/vnc.c @@ -0,0 +1,663 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2004 + + libvnc + +*/ + +#include "vnc.h" + +/******************************************************************************/ +int lib_mod_event(int handle, int msg, int param1, int param2) +{ + struct vnc* v; + struct stream* s; + int key; + + make_stream(s); + v = (struct vnc*)handle; + if (msg >= 15 && msg <= 16) + { + key = 0; + if (param2 == 0xffff) + { + key = param1; + } + else + { + switch (param1) + { + case 0x0001: key = 0xff1b; break; /* ecs */ + case 0x000e: key = 0xff08; break; /* backspace */ + case 0x000f: key = 0xff09; break; /* tab */ + case 0x001c: key = 0xff0d; break; /* enter */ + /* left-right control */ + case 0x001d: key = (param2 & 0x0100) ? 0xffe3 : 0xffe4; break; + case 0x002a: key = 0xffe1; break; /* left shift */ + case 0x0036: key = 0xffe2; break; /* right shift */ + /* left-right alt */ + case 0x0038: key = (param2 & 0x0100) ? 0xffe9 : 0xffea; break; + case 0x003b: key = 0xffbe; break; /* F1 */ + case 0x003c: key = 0xffbf; break; /* F2 */ + case 0x003d: key = 0xffc0; break; /* F3 */ + case 0x003e: key = 0xffc1; break; /* F4 */ + case 0x003f: key = 0xffc2; break; /* F5 */ + case 0x0040: key = 0xffc3; break; /* F6 */ + case 0x0041: key = 0xffc4; break; /* F7 */ + case 0x0042: key = 0xffc5; break; /* F8 */ + case 0x0043: key = 0xffc6; break; /* F9 */ + case 0x0044: key = 0xffc7; break; /* F10 */ + case 0x0047: key = 0xff50; break; /* home */ + case 0x0048: key = 0xff52; break; /* up arrow */ + case 0x0049: key = 0xff55; break; /* page up */ + case 0x004b: key = 0xff51; break; /* left arrow */ + case 0x004d: key = 0xff53; break; /* right arrow */ + case 0x004f: key = 0xff57; break; /* end */ + case 0x0050: key = 0xff54; break; /* down arrow */ + case 0x0051: key = 0xff56; break; /* page down */ + case 0x0052: key = 0xff63; break; /* insert */ + case 0x0053: key = 0xffff; break; /* delete */ + case 0x0057: key = 0xffc8; break; /* F11 */ + case 0x0058: key = 0xffc9; break; /* F12 */ + } + } + if (key > 0) + { + init_stream(s, 8192); + out_uint8(s, 4); + out_uint8(s, msg == 15); /* down flag */ + out_uint8s(s, 2); + out_uint32_be(s, key); + if (g_tcp_force_send(v->sck, s->data, 8) != 0) + { + free_stream(s); + return 1; + } + } + } + else if (msg >= 100 && msg <= 110) + { + switch (msg) + { + case 100: break; /* WM_MOUSEMOVE */ + case 101: v->mod_mouse_state &= ~1; break; /* WM_LBUTTONUP */ + case 102: v->mod_mouse_state |= 1; break; /* WM_LBUTTONDOWN */ + case 103: v->mod_mouse_state &= ~4; break; /* WM_RBUTTONUP */ + case 104: v->mod_mouse_state |= 4; break; /* WM_RBUTTONDOWN */ + case 105: v->mod_mouse_state &= ~2; break; + case 106: v->mod_mouse_state |= 2; break; + case 107: v->mod_mouse_state &= ~8; break; + case 108: v->mod_mouse_state |= 8; break; + case 109: v->mod_mouse_state &= ~16; break; + case 110: v->mod_mouse_state |= 16; break; + } + init_stream(s, 8192); + out_uint8(s, 5); + out_uint8(s, v->mod_mouse_state); + out_uint16_be(s, param1); + out_uint16_be(s, param2); + if (g_tcp_force_send(v->sck, s->data, 6) != 0) + { + free_stream(s); + return 1; + } + } + free_stream(s); + return 0; +} + +//****************************************************************************** +int get_pixel_safe(char* data, int x, int y, int width, int height, int bpp) +{ + int start; + int shift; + + if (x < 0) + return 0; + if (y < 0) + return 0; + if (x >= width) + return 0; + if (y >= height) + return 0; + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + return (data[start] & (0x80 >> shift)) != 0; + } + else if (bpp == 4) + { + width = (width + 1) / 2; + start = y * width + x / 2; + shift = x % 2; + if (shift == 0) + return (data[start] & 0xf0) >> 4; + else + return data[start] & 0x0f; + } + else if (bpp == 8) + { + return *(((unsigned char*)data) + (y * width + x)); + } + else if (bpp == 15 || bpp == 16) + { + return *(((unsigned short*)data) + (y * width + x)); + } + return 0; +} + +/******************************************************************************/ +void set_pixel_safe(char* data, int x, int y, int width, int height, int bpp, + int pixel) +{ + int start; + int shift; + + if (x < 0) + return; + if (y < 0) + return; + if (x >= width) + return; + if (y >= height) + return; + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + if (pixel & 1) + data[start] = data[start] | (0x80 >> shift); + else + data[start] = data[start] & ~(0x80 >> shift); + } + else if (bpp == 15 || bpp == 16) + { + *(((unsigned short*)data) + (y * width + x)) = pixel; + } + else if (bpp == 24) + { + *(data + (3 * (y * width + x)) + 0) = pixel >> 0; + *(data + (3 * (y * width + x)) + 1) = pixel >> 8; + *(data + (3 * (y * width + x)) + 2) = pixel >> 16; + } +} + +/******************************************************************************/ +int split_color(int pixel, int* r, int* g, int* b, int bpp, int* palette) +{ + if (bpp == 8) + { + if (pixel >= 0 && pixel < 256 && palette != 0) + { + *r = (palette[pixel] >> 16) & 0xff; + *g = (palette[pixel] >> 8) & 0xff; + *b = (palette[pixel] >> 0) & 0xff; + } + } + else if (bpp == 16) + { + *r = ((pixel >> 8) & 0xf8) | ((pixel >> 13) & 0x7); + *g = ((pixel >> 3) & 0xfc) | ((pixel >> 9) & 0x3); + *b = ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x7); + } + return 0; +} + +/******************************************************************************/ +int make_color(int r, int g, int b, int bpp) +{ + if (bpp == 24) + { + return (r << 16) | (g << 8) | b; + } + return 0; +} + +/******************************************************************************/ +int lib_framebuffer_update(struct vnc* v) +{ + char* data; + char* d1; + char* d2; + char cursor_data[32 * (32 * 3)]; + char cursor_mask[32 * (32 / 8)]; + int num_recs; + int i; + int j; + int k; + int x; + int y; + int cx; + int cy; + int srcx; + int srcy; + int encoding; + int Bpp; + int pixel; + int r; + int g; + int b; + struct stream* s; + + Bpp = (v->mod_bpp + 7) / 8; + make_stream(s); + init_stream(s, 8192); + if (g_tcp_force_recv(v->sck, s->data, 3) != 0) + { + free_stream(s); + return 1; + } + in_uint8s(s, 1); + in_uint16_be(s, num_recs); + for (i = 0; i < num_recs; i++) + { + init_stream(s, 8192); + if (g_tcp_force_recv(v->sck, s->data, 12) != 0) + { + free_stream(s); + return 1; + } + in_uint16_be(s, x); + in_uint16_be(s, y); + in_uint16_be(s, cx); + in_uint16_be(s, cy); + in_uint32_be(s, encoding); + if (encoding == 0) /* raw */ + { + data = (char*)g_malloc(cx * cy * Bpp, 0); + if (g_tcp_force_recv(v->sck, data, cx * cy * Bpp) != 0) + { + g_free(data); + free_stream(s); + return 1; + } + v->server_begin_update((int)v); + v->server_paint_rect((int)v, x, y, cx, cy, data); + v->server_end_update((int)v); + g_free(data); + } + else if (encoding == 1) /* copy rect */ + { + init_stream(s, 8192); + if (g_tcp_force_recv(v->sck, s->data, 4) != 0) + { + free_stream(s); + return 1; + } + in_uint16_be(s, srcx); + in_uint16_be(s, srcy); + v->server_begin_update((int)v); + v->server_screen_blt((int)v, x, y, cx, cy, srcx, srcy); + v->server_end_update((int)v); + } + else if (encoding == 0xffffff11) /* cursor */ + { + g_memset(cursor_data, 0, 32 * (32 * 3)); + g_memset(cursor_mask, 0, 32 * (32 / 8)); + init_stream(s, 8192); + if (g_tcp_force_recv(v->sck, s->data, + cx * cy * Bpp + ((cx + 7) / 8) * cy) != 0) + { + free_stream(s); + return 1; + } + in_uint8p(s, d1, cx * cy * Bpp); + in_uint8p(s, d2, ((cx + 7) / 8) * cy); + for (j = 0; j < 32; j++) + { + for (k = 0; k < 32; k++) + { + pixel = get_pixel_safe(d2, k, 31 - j, cx, cy, 1); + set_pixel_safe(cursor_mask, k, j, 32, 32, 1, !pixel); + if (pixel) + { + pixel = get_pixel_safe(d1, k, 31 - j, cx, cy, v->mod_bpp); + split_color(pixel, &r, &g, &b, v->mod_bpp, v->palette); + pixel = make_color(r, g, b, 24); + set_pixel_safe(cursor_data, k, j, 32, 32, 24, pixel); + } + } + } + v->server_set_cursor((int)v, x, y, cursor_data, cursor_mask); + } + } + /* FrambufferUpdateRequest */ + init_stream(s, 8192); + out_uint8(s, 3); + out_uint8(s, 1); + out_uint16_be(s, 0); + out_uint16_be(s, 0); + out_uint16_be(s, v->mod_width); + out_uint16_be(s, v->mod_height); + if (g_tcp_force_send(v->sck, s->data, 10) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; +} + +/******************************************************************************/ +int lib_clip_data(struct vnc* v) +{ + struct stream* s; + int size; + + make_stream(s); + init_stream(s, 8192); + if (g_tcp_force_recv(v->sck, s->data, 7) != 0) + { + free_stream(s); + return 1; + } + in_uint8s(s, 3); + in_uint32_be(s, size); + init_stream(s, 8192); + if (g_tcp_force_recv(v->sck, s->data, size) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; +} + +/******************************************************************************/ +int lib_palette_update(struct vnc* v) +{ + struct stream* s; + int first_color; + int num_colors; + int i; + int r; + int g; + int b; + + make_stream(s); + init_stream(s, 8192); + if (g_tcp_force_recv(v->sck, s->data, 5) != 0) + { + free_stream(s); + return 1; + } + in_uint8s(s, 1); + in_uint16_be(s, first_color); + in_uint16_be(s, num_colors); + init_stream(s, 8192); + if (g_tcp_force_recv(v->sck, s->data, num_colors * 6) != 0) + { + free_stream(s); + return 1; + } + for (i = 0; i < num_colors; i++) + { + in_uint16_be(s, r); + in_uint16_be(s, g); + in_uint16_be(s, b); + r = r >> 8; + g = g >> 8; + b = b >> 8; + v->palette[first_color + i] = (r << 16) | (g << 8) | b; + } + v->server_begin_update((int)v); + v->server_palette((int)v, v->palette); + v->server_end_update((int)v); + free_stream(s); + return 0; +} + +/******************************************************************************/ +int lib_mod_signal(int handle) +{ + struct vnc* v; + char type; + + v = (struct vnc*)handle; + if (g_tcp_force_recv(v->sck, &type, 1) != 0) + { + return 1; + } + if (type == 0) /* framebuffer update */ + { + if (lib_framebuffer_update(v) != 0) + { + return 1; + } + } + else if (type == 1) /* palette */ + { + if (lib_palette_update(v) != 0) + { + return 1; + } + } + else if (type == 3) /* clipboard */ + { + if (lib_clip_data(v) != 0) + { + return 1; + } + } + else + { + g_printf("unknown in lib_mod_signal %d\n\r", type); + } + return 0; +} + +/******************************************************************************/ +int lib_mod_start(int handle, int w, int h, int bpp) +{ + struct vnc* v; + + v = (struct vnc*)handle; + v->server_begin_update(handle); + v->server_fill_rect(handle, 0, 0, w, h, 0); + v->server_end_update(handle); + v->server_width = w; + v->server_height = h; + v->server_bpp = bpp; + return 0; +} + +/******************************************************************************/ +int lib_mod_connect(int handle, char* ip, char* port, + char* username, char* password) +{ + char cursor_data[32 * (32 * 3)]; + char cursor_mask[32 * (32 / 8)]; + struct vnc* v; + struct stream* s; + struct stream* pixel_format; + int error; + int i; + + make_stream(s); + make_stream(pixel_format); + v = (struct vnc*)handle; + v->sck = g_tcp_socket(); + error = g_tcp_connect(v->sck, ip, port); + if (error == 0) + { + g_tcp_set_non_blocking(v->sck); + /* protocal version */ + init_stream(s, 8192); + g_tcp_force_recv(v->sck, s->data, 12); + g_tcp_force_send(v->sck, "RFB 003.003\n", 12); + /* sec type */ + init_stream(s, 8192); + g_tcp_force_recv(v->sck, s->data, 4); + in_uint32_be(s, i); + if (i == 2) /* dec the password and the server random */ + { + init_stream(s, 8192); + g_tcp_force_recv(v->sck, s->data, 16); + rfbEncryptBytes((unsigned char*)s->data, password); + g_tcp_force_send(v->sck, s->data, 16); + } + else + error = 1; + } + if (error == 0) + { + /* sec result */ + init_stream(s, 8192); + g_tcp_force_recv(v->sck, s->data, 4); + in_uint32_be(s, i); + if (i != 0) + error = 2; + } + if (error == 0) + { + init_stream(s, 8192); + s->data[0] = 1; + g_tcp_force_send(v->sck, s->data, 1); /* share flag */ + g_tcp_force_recv(v->sck, s->data, 4); /* server init */ + in_uint16_be(s, v->mod_width); + in_uint16_be(s, v->mod_height); + init_stream(pixel_format, 8192); + g_tcp_force_recv(v->sck, pixel_format->data, 16); + in_uint8(pixel_format, v->mod_bpp); + init_stream(s, 8192); + g_tcp_force_recv(v->sck, s->data, 4); /* name len */ + in_uint32_be(s, i); + if (i > 255 || i < 0) + error = 3; + else + { + g_tcp_force_recv(v->sck, v->mod_name, i); + v->mod_name[i] = 0; + } + /* should be connected */ + } + if (error == 0) + { + /* SetPixelFormat */ + init_stream(s, 8192); + out_uint8(s, 0); + out_uint8(s, 0); + out_uint8(s, 0); + out_uint8(s, 0); + init_stream(pixel_format, 8192); + if (v->mod_bpp == 8) + { + out_uint8(pixel_format, 8); /* bits per pixel */ + out_uint8(pixel_format, 8); /* depth */ + out_uint8(pixel_format, 0); /* big endian */ + out_uint8(pixel_format, 0); /* true color flag */ + out_uint16_be(pixel_format, 0); /* red max */ + out_uint16_be(pixel_format, 0); /* green max */ + out_uint16_be(pixel_format, 0); /* blue max */ + out_uint8(pixel_format, 0); /* red shift */ + out_uint8(pixel_format, 0); /* green shift */ + out_uint8(pixel_format, 0); /* blue shift */ + out_uint8s(pixel_format, 3); /* pad */ + } + out_uint8a(s, pixel_format->data, 16); + g_tcp_force_send(v->sck, s->data, 20); + /* SetEncodings */ + init_stream(s, 8192); + out_uint8(s, 2); + out_uint8(s, 0); + out_uint16_be(s, 3); + out_uint32_be(s, 0); /* raw */ + out_uint32_be(s, 1); /* copy rect */ + out_uint32_be(s, 0xffffff11); /* cursor */ + g_tcp_force_send(v->sck, s->data, 4 + 3 * 4); + /* FrambufferUpdateRequest */ + init_stream(s, 8192); + out_uint8(s, 3); + out_uint8(s, 0); + out_uint16_be(s, 0); + out_uint16_be(s, 0); + out_uint16_be(s, v->mod_width); + out_uint16_be(s, v->mod_height); + g_tcp_force_send(v->sck, s->data, 10); + } + if (error == 0) + { + v->server_error_popup((int)v, "hi", "Hi"); + if (v->server_bpp != v->mod_bpp) + error = 4; + } + /* set almost null cursor */ + g_memset(cursor_data, 0, 32 * (32 * 3)); + g_memset(cursor_data + (32 * (32 * 3) - 1 * 32 * 3), 0xff, 9); + g_memset(cursor_data + (32 * (32 * 3) - 2 * 32 * 3), 0xff, 9); + g_memset(cursor_data + (32 * (32 * 3) - 3 * 32 * 3), 0xff, 9); + g_memset(cursor_mask, 0xff, 32 * (32 / 8)); + v->server_set_cursor((int)v, 0, 0, cursor_data, cursor_mask); + free_stream(s); + free_stream(pixel_format); + return error; +} + +/******************************************************************************/ +int lib_mod_invalidate(int handle, int x, int y, int cx, int cy) +{ + struct vnc* v; + struct stream* s; + + make_stream(s); + v = (struct vnc*)handle; + /* FrambufferUpdateRequest */ + init_stream(s, 8192); + out_uint8(s, 3); + out_uint8(s, 0); + out_uint16_be(s, x); + out_uint16_be(s, y); + out_uint16_be(s, cx); + out_uint16_be(s, cy); + g_tcp_force_send(v->sck, s->data, 10); + free_stream(s); + return 0; +} + +/******************************************************************************/ +int mod_init() +{ + struct vnc* v; + + v = (struct vnc*)g_malloc(sizeof(struct vnc), 1); + /* set client functions */ + v->size = sizeof(struct vnc); + v->handle = (int)v; + v->mod_connect = lib_mod_connect; + v->mod_start = lib_mod_start; + v->mod_event = lib_mod_event; + v->mod_signal = lib_mod_signal; + v->mod_invalidate = lib_mod_invalidate; + return (int)v; +} + +/******************************************************************************/ +int mod_exit(int handle) +{ + struct vnc* v; + + if (handle == 0) + return 0; + v = (struct vnc*)handle; + g_tcp_close(v->sck); + g_free(v); + return 0; +} diff --git a/vnc/vnc.h b/vnc/vnc.h new file mode 100644 index 00000000..81079b73 --- /dev/null +++ b/vnc/vnc.h @@ -0,0 +1,153 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2004 + + libvnc + +*/ + +/* check endianess */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define L_ENDIAN +#elif __BYTE_ORDER == __BIG_ENDIAN +#define B_ENDIAN +#endif +/* check if we need to align data */ +#if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \ + defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ + defined(__ia64__) +#define NEED_ALIGN +#endif +/* include other h files */ +#include "parse.h" + +#ifdef _WIN32 +#define THREAD_RV unsigned long +#define THREAD_CC __stdcall +#else +#define THREAD_RV void* +#define THREAD_CC +#endif + +void rfbEncryptBytes(unsigned char *bytes, char *passwd); + +/* os_calls.c */ +int g_init_system(void); +int g_exit_system(void); +void g_printf(char *format, ...); +void g_hexdump(char* p, int len); +void* g_malloc(int size, int zero); +void* g_malloc1(int size, int zero); +void g_free(void* ptr); +void g_free1(void* ptr); +void g_memset(void* ptr, int val, int size); +void g_memcpy(void* d_ptr, const void* s_ptr, int size); +int g_getchar(void); +int g_tcp_socket(void); +int g_tcp_local_socket(void); +void g_tcp_close(int sck); +int g_tcp_connect(int sck, char* address, char* port); +int g_tcp_force_send(int sck, char* data, int len); +int g_tcp_force_recv(int sck, char* data, int len); +int g_tcp_set_non_blocking(int sck); +int g_tcp_bind(int sck, char* port); +int g_tcp_local_bind(int sck, char* port); +int g_tcp_listen(int sck); +int g_tcp_accept(int sck); +int g_tcp_recv(int sck, void* ptr, int len, int flags); +int g_tcp_send(int sck, void* ptr, int len, int flags); +int g_tcp_last_error_would_block(int sck); +int g_tcp_select(int sck1, int sck2); +int g_is_term(void); +void g_set_term(int in_val); +void g_sleep(int msecs); +int g_thread_create(THREAD_RV (THREAD_CC * start_routine)(void*), void* arg); +void* g_rc4_info_create(void); +void g_rc4_info_delete(void* rc4_info); +void g_rc4_set_key(void* rc4_info, char* key, int len); +void g_rc4_crypt(void* rc4_info, char* data, int len); +void* g_sha1_info_create(void); +void g_sha1_info_delete(void* sha1_info); +void g_sha1_clear(void* sha1_info); +void g_sha1_transform(void* sha1_info, char* data, int len); +void g_sha1_complete(void* sha1_info, char* data); +void* g_md5_info_create(void); +void g_md5_info_delete(void* md5_info); +void g_md5_clear(void* md5_info); +void g_md5_transform(void* md5_info, char* data, int len); +void g_md5_complete(void* md5_info, char* data); +int g_mod_exp(char* out, char* in, char* mod, char* exp); +void g_random(char* data, int len); +int g_abs(int i); +int g_memcmp(void* s1, void* s2, int len); +int g_file_open(char* file_name); +int g_file_close(int fd); +int g_file_read(int fd, char* ptr, int len); +int g_file_write(int fd, char* ptr, int len); +int g_file_seek(int fd, int offset); +int g_file_lock(int fd, int start, int len); +int g_strlen(char* text); +char* g_strcpy(char* dest, char* src); +char* g_strncpy(char* dest, char* src, int len); +char* g_strcat(char* dest, char* src); +char* g_strdup(char* in); +int g_load_library(char* in); +int g_free_library(int lib); +void* g_get_proc_address(int lib, char* name); + +#define COLOR16(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) + +struct vnc +{ + int size; /* size of this struct */ + /* client functions */ + int (*mod_start)(int handle, int w, int h, int bpp); + int (*mod_connect)(int handle, char* ip, char* port, + char* username, char* password); + int (*mod_event)(int handle, int msg, int param1, int param2); + int (*mod_signal)(int handle); + int (*mod_invalidate)(int handle, int x, int y, int cx, int cy); + int d1[95]; + /* server functions */ + int (*server_begin_update)(int handle); + int (*server_end_update)(int handle); + int (*server_fill_rect)(int handle, int x, int y, int cx, int cy, + int color); + int (*server_screen_blt)(int handle, int x, int y, int cx, int cy, + int srcx, int srcy); + int (*server_paint_rect)(int handle, int x, int y, int cx, int cy, + char* data); + int (*server_set_cursor)(int handle, int x, int y, char* data, char* mask); + int (*server_palette)(int handle, int* palette); + int (*server_error_popup)(int handle, char* error, char* caption); + int d2[92]; + /* common */ + int handle; /* pointer to self as int */ + int wm; + int painter; + int sck; + /* mod data */ + int server_width; + int server_height; + int server_bpp; + int mod_width; + int mod_height; + int mod_bpp; + char mod_name[256]; + int mod_mouse_state; + int palette[256]; +}; diff --git a/vnc/vncauth.c b/vnc/vncauth.c new file mode 100644 index 00000000..e2d4b97c --- /dev/null +++ b/vnc/vncauth.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * vncauth.c - Functions for VNC password management and authentication. + */ + +/* + stripped down Jay Sorg for xrdp +*/ + +#include +#include +#include +#include "d3des.h" +#include +#include + + +void rfbEncryptBytes(unsigned char *bytes, char *passwd) +{ + unsigned char key[8]; + unsigned int i; + + /* key is simply password padded with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + key[i] = passwd[i]; + } else { + key[i] = 0; + } + } + + rfbDesKey(key, EN0); + + for (i = 0; i < 16; i += 8) { + rfbDes(bytes+i, bytes+i); + } +} diff --git a/xrdp/Makefile b/xrdp/Makefile index c6f5eafd..c26d1852 100644 --- a/xrdp/Makefile +++ b/xrdp/Makefile @@ -2,7 +2,9 @@ XRDPOBJ = xrdp.o os_calls.o xrdp_tcp.o xrdp_iso.o xrdp_mcs.o xrdp_sec.o \ xrdp_rdp.o xrdp_process.o xrdp_listen.o xrdp_orders.o \ xrdp_bitmap.o xrdp_wm.o xrdp_painter.o xrdp_list.o \ - xrdp_region.o xrdp_cache.o xrdp_font.o funcs.o + xrdp_region.o xrdp_cache.o xrdp_font.o funcs.o \ + xrdp_login_wnd.o xrdp_file.o + #CFLAGS = -Wall -O2 -DXRDP_DEBUG CFLAGS = -Wall -O2 LDFLAGS = -L /usr/gnu/lib diff --git a/xrdp/constants.h b/xrdp/constants.h index dd5ec02f..dd473ccc 100644 --- a/xrdp/constants.h +++ b/xrdp/constants.h @@ -414,8 +414,17 @@ #define BUTTON_STATE_DOWN 1 /* messages */ -#define WM_PAINT 3 -#define WM_KEYDOWN 15 -#define WM_KEYUP 16 -#define WM_MOUSEMOVE 100 -#define WM_LBUTTONUP 101 +#define WM_PAINT 3 +#define WM_KEYDOWN 15 +#define WM_KEYUP 16 +#define WM_MOUSEMOVE 100 +#define WM_LBUTTONUP 101 +#define WM_LBUTTONDOWN 102 +#define WM_RBUTTONUP 103 +#define WM_RBUTTONDOWN 104 +#define WM_BUTTON3UP 105 +#define WM_BUTTON3DOWN 106 +#define WM_BUTTON4UP 107 +#define WM_BUTTON4DOWN 108 +#define WM_BUTTON5UP 109 +#define WM_BUTTON5DOWN 110 diff --git a/xrdp/makefile_win32 b/xrdp/makefile_win32 index 37a76bdf..5f01cbba 100644 --- a/xrdp/makefile_win32 +++ b/xrdp/makefile_win32 @@ -1,28 +1,28 @@ -# borland windows makefile -# -# this assumes openssl and borland free command line tools are installed -# this assumes c:\windows is windows directory -# -# run 'set PATH=c:\borland\bcc55\bin' and run 'make all' -# - -XRDPOBJ = xrdp.obj os_calls.obj xrdp_tcp.obj xrdp_iso.obj xrdp_mcs.obj \ - xrdp_sec.obj xrdp_rdp.obj xrdp_process.obj xrdp_listen.obj \ - xrdp_orders.obj xrdp_bitmap.obj xrdp_wm.obj xrdp_painter.obj \ - xrdp_list.obj xrdp_region.obj xrdp_cache.obj xrdp_font.obj \ - funcs.obj - -CFLAGS = -w- -O2 -Ic:\borland\bcc55\include -Ic:\openssl\include -LDFLAGS = -Lc:\borland\bcc55\lib - -xrdp: $(XRDPOBJ) - $(CC) $(LDFLAGS) libeay32.lib $(XRDPOBJ) - -all: lib xrdp - -clean: - del *.obj *.o xrdp.exe - -lib: - implib -a -w libeay32.lib c:\windows\system32\libeay32.dll - +# borland windows makefile +# +# this assumes openssl and borland free command line tools are installed +# this assumes c:\windows is windows directory +# +# run 'set PATH=c:\borland\bcc55\bin' and run 'make all' +# + +XRDPOBJ = xrdp.obj os_calls.obj xrdp_tcp.obj xrdp_iso.obj xrdp_mcs.obj \ + xrdp_sec.obj xrdp_rdp.obj xrdp_process.obj xrdp_listen.obj \ + xrdp_orders.obj xrdp_bitmap.obj xrdp_wm.obj xrdp_painter.obj \ + xrdp_list.obj xrdp_region.obj xrdp_cache.obj xrdp_font.obj \ + funcs.obj xrdp_login_wnd.obj xrdp_file.obj + +CFLAGS = -w- -O2 -Ic:\borland\bcc55\include -Ic:\openssl\include +LDFLAGS = -Lc:\borland\bcc55\lib + +xrdp: $(XRDPOBJ) + $(CC) $(LDFLAGS) libeay32.lib $(XRDPOBJ) + +all: lib xrdp + +clean: + del *.obj *.o xrdp.exe + +lib: + implib -a -w libeay32.lib c:\windows\system32\libeay32.dll + diff --git a/xrdp/os_calls.c b/xrdp/os_calls.c index 164c93f3..cd921f01 100644 --- a/xrdp/os_calls.c +++ b/xrdp/os_calls.c @@ -33,6 +33,9 @@ #include #include #include +#include +#include +#include #endif #include #include @@ -74,6 +77,10 @@ int g_init_system(void) #endif #ifdef MEMLEAK g_memlist = xrdp_list_create(); + printf("some info\n\r"); + printf("sizeof xrdp_bitmap is %d\n\r", sizeof(struct xrdp_bitmap)); + printf("sizeof xrdp_wm is %d\n\r", sizeof(struct xrdp_wm)); + printf("sizeof stream is %d\n\r", sizeof(struct stream)); #endif return 0; } @@ -261,6 +268,28 @@ void g_tcp_close(int sck) #endif } +/*****************************************************************************/ +int g_tcp_connect(int sck, char* address, char* port) +{ + struct sockaddr_in s; + struct hostent* h; + + g_memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons(atoi(port)); + s.sin_addr.s_addr = inet_addr(address); + if (s.sin_addr.s_addr == INADDR_NONE) + { + h = gethostbyname(address); + if (h != 0) + if (h->h_name != 0) + if (h->h_addr_list != 0) + if ((*(h->h_addr_list)) != 0) + s.sin_addr.s_addr = *((int*)(*(h->h_addr_list))); + } + return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + /*****************************************************************************/ int g_tcp_set_non_blocking(int sck) { @@ -349,6 +378,7 @@ int g_tcp_select(int sck1, int sck2) fd_set rfds; struct timeval time; int max; + int rv; time.tv_sec = 0; time.tv_usec = 0; @@ -358,7 +388,16 @@ int g_tcp_select(int sck1, int sck2) max = sck1; if (sck2 > max) max = sck2; - return select(max + 1, &rfds, 0, 0, &time); + rv = select(max + 1, &rfds, 0, 0, &time); + if (rv > 0) + { + rv = 0; + if (FD_ISSET(((unsigned int)sck1), &rfds)) + rv = rv | 1; + if (FD_ISSET(((unsigned int)sck2), &rfds)) + rv = rv | 2; + } + return rv; } /*****************************************************************************/ @@ -692,3 +731,32 @@ char* g_strdup(char* in) g_strcpy(p, in); return p; } + +/*****************************************************************************/ +int g_strcmp(char* c1, char* c2) +{ + return strcmp(c1, c2); +} + +/*****************************************************************************/ +int g_load_library(char* in) +{ + return (int)dlopen(in, RTLD_LOCAL | RTLD_LAZY); +} + +/*****************************************************************************/ +int g_free_library(int lib) +{ + if (lib == 0) + return 0; + return dlclose((void*)lib); +} + +/*****************************************************************************/ +/* returns NULL if not found */ +void* g_get_proc_address(int lib, char* name) +{ + if (lib == 0) + return 0; + return dlsym((void*)lib, name); +} diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index d5f5f6f6..c8c199ec 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -53,6 +53,7 @@ int g_getchar(void); int g_tcp_socket(void); int g_tcp_local_socket(void); void g_tcp_close(int sck); +int g_tcp_connect(int sck, char* address, char* port); int g_tcp_set_non_blocking(int sck); int g_tcp_bind(int sck, char* port); int g_tcp_local_bind(int sck, char* port); @@ -95,6 +96,10 @@ char* g_strcpy(char* dest, char* src); char* g_strncpy(char* dest, char* src, int len); char* g_strcat(char* dest, char* src); char* g_strdup(char* in); +int g_strcmp(char* c1, char* c2); +int g_load_library(char* in); +int g_free_library(int lib); +void* g_get_proc_address(int lib, char* name); /* xrdp_tcp.c */ struct xrdp_tcp* xrdp_tcp_create(struct xrdp_iso* owner); @@ -204,14 +209,17 @@ int xrdp_wm_send_palette(struct xrdp_wm* self); int xrdp_wm_init(struct xrdp_wm* self); int xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap, int x, int y, int cx, int cy); +int xrdp_wm_set_focused(struct xrdp_wm* self, struct xrdp_bitmap* wnd); int xrdp_wm_get_vis_region(struct xrdp_wm* self, struct xrdp_bitmap* bitmap, int x, int y, int cx, int cy, - struct xrdp_region* region); + struct xrdp_region* region, int clip_children); int xrdp_wm_mouse_move(struct xrdp_wm* self, int x, int y); int xrdp_wm_mouse_click(struct xrdp_wm* self, int x, int y, int but, int down); int xrdp_wm_key(struct xrdp_wm* self, int device_flags, int scan_code); int xrdp_wm_key_sync(struct xrdp_wm* self, int device_flags, int key_flags); int xrdp_wm_pu(struct xrdp_wm* self, struct xrdp_bitmap* control); +int xrdp_wm_send_cursor(struct xrdp_wm* self, int cache_idx, + char* data, char* mask, int x, int y); /* xrdp_process.c */ struct xrdp_process* xrdp_process_create(struct xrdp_listen* owner); @@ -238,7 +246,11 @@ int xrdp_region_get_rect(struct xrdp_region* self, int index, /* xrdp_bitmap.c */ struct xrdp_bitmap* xrdp_bitmap_create(int width, int height, int bpp, int type); +struct xrdp_bitmap* xrdp_bitmap_create_with_data(int width, int height, + int bpp, char* data); void xrdp_bitmap_delete(struct xrdp_bitmap* self); +struct xrdp_bitmap* xrdp_bitmap_get_child_by_id(struct xrdp_bitmap* self, + int id); int xrdp_bitmap_set_focus(struct xrdp_bitmap* self, int focused); int xrdp_bitmap_load(struct xrdp_bitmap* self, char* filename, int* palette); int xrdp_bitmap_get_pixel(struct xrdp_bitmap* self, int x, int y); @@ -305,3 +317,8 @@ int add_char_at(char* text, char ch, int index); int remove_char_at(char* text, int index); int set_string(char** in_str, char* in); +int xrdp_login_wnd_create(struct xrdp_wm* self); + +int xrdp_file_read_sections(int fd, struct xrdp_list* names); +int xrdp_file_read_section(int fd, char* section, struct xrdp_list* names, + struct xrdp_list* values); diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini new file mode 100644 index 00000000..e85f9e6d --- /dev/null +++ b/xrdp/xrdp.ini @@ -0,0 +1,20 @@ + +[globals] + +[vnc1] +name=vnc test +lib=../vnc/libvnc.so +auth=local +ip=127.0.0.1 +port=5901 +user=n/a +password=master + +[vnc2] +name=vnc test2 +lib=../vnc/libvnc.so +auth=local +ip=205.5.61.3 +port=5900 +user=n/a +password=ecs diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c index b7e18599..21264e6c 100644 --- a/xrdp/xrdp_bitmap.c +++ b/xrdp/xrdp_bitmap.c @@ -48,15 +48,33 @@ struct xrdp_bitmap* xrdp_bitmap_create(int width, int height, int bpp, self->data = (char*)g_malloc(width * height * Bpp, 1); if (self->type != WND_TYPE_BITMAP) self->child_list = xrdp_list_create(); - self->line_size = ((width + 3) & ~3) * Bpp; + self->line_size = width * Bpp; if (self->type == WND_TYPE_COMBO) { self->string_list = xrdp_list_create(); self->string_list->auto_free = 1; + self->data_list = xrdp_list_create(); + self->data_list->auto_free = 1; } return self; } +/*****************************************************************************/ +struct xrdp_bitmap* xrdp_bitmap_create_with_data(int width, int height, + int bpp, char* data) +{ + struct xrdp_bitmap* self; + + self = (struct xrdp_bitmap*)g_malloc(sizeof(struct xrdp_bitmap), 1); + self->type = WND_TYPE_BITMAP; + self->width = width; + self->height = height; + self->bpp = bpp; + self->data = data; + self->do_not_free_data = 1; + return self; +} + /*****************************************************************************/ void xrdp_bitmap_delete(struct xrdp_bitmap* self) { @@ -79,18 +97,44 @@ void xrdp_bitmap_delete(struct xrdp_bitmap* self) self->wm->button_down = 0; if (self->wm->popup_wnd == self) self->wm->popup_wnd = 0; + if (self->wm->login_window == self) + self->wm->login_window = 0; } if (self->child_list != 0) { - for (i = 0; i < self->child_list->count; i++) + for (i = self->child_list->count - 1; i >= 0; i--) xrdp_bitmap_delete((struct xrdp_bitmap*)self->child_list->items[i]); xrdp_list_delete(self->child_list); } + if (self->parent != 0) + { + i = xrdp_list_index_of(self->parent->child_list, (int)self); + if (i >= 0) + xrdp_list_remove_item(self->parent->child_list, i); + } xrdp_list_delete(self->string_list); - g_free(self->data); + xrdp_list_delete(self->data_list); + if (!self->do_not_free_data) + g_free(self->data); g_free(self); } +/*****************************************************************************/ +struct xrdp_bitmap* xrdp_bitmap_get_child_by_id(struct xrdp_bitmap* self, + int id) +{ + int i; + struct xrdp_bitmap* b; + + for (i = 0; i < self->child_list->count; i++) + { + b = (struct xrdp_bitmap*)xrdp_list_get_item(self->child_list, i); + if (b->id == id) + return b; + } + return 0; +} + /*****************************************************************************/ /* if focused is true focus this window else unfocus it */ /* returns error */ @@ -162,7 +206,7 @@ int xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height) case 16: Bpp = 2; break; } self->data = (char*)g_malloc(width * height * Bpp, 1); - self->line_size = ((width + 3) & ~3) * Bpp; + self->line_size = width * Bpp; return 0; } @@ -541,8 +585,24 @@ int xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect) } else if (self->type == WND_TYPE_SCREEN) /* 2 */ { - painter->fg_color = self->bg_color; - xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height); + if (self->wm->mod != 0) + { + if (self->wm->mod->mod_invalidate != 0) + { + if (rect != 0) + { + self->wm->mod->mod_invalidate((int)self->wm->mod, + rect->left, rect->top, + rect->right - rect->left, + rect->bottom - rect->top); + } + } + } + else + { + painter->fg_color = self->bg_color; + xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height); + } } else if (self->type == WND_TYPE_BUTTON) /* 3 */ { diff --git a/xrdp/xrdp_cache.c b/xrdp/xrdp_cache.c index f9df7ad5..aab31b57 100644 --- a/xrdp/xrdp_cache.c +++ b/xrdp/xrdp_cache.c @@ -69,6 +69,7 @@ int xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap) for (i = 0; i < 3; i++) { for (j = 0; j < 600; j++) + //for (j = 0; (i == 0 && j < 600) || (i == 1 && j < 300); j++) { if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap)) { @@ -85,6 +86,7 @@ int xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap) for (i = 0; i < 3; i++) { for (j = 0; j < 600; j++) + //for (j = 0; (i == 0 && j < 600) || (i == 1 && j < 300); j++) { if (self->bitmap_items[i][j].stamp < oldest) { diff --git a/xrdp/xrdp_file.c b/xrdp/xrdp_file.c new file mode 100644 index 00000000..00948174 --- /dev/null +++ b/xrdp/xrdp_file.c @@ -0,0 +1,201 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2004 + + read a config file + +*/ + +#include "xrdp.h" + +/*****************************************************************************/ +int xrdp_file_read_sections(int fd, struct xrdp_list* names) +{ + struct stream* s; + char text[256]; + char c; + int in_it; + int in_it_index; + int len; + int index; + + g_file_seek(fd, 0); + in_it_index = 0; + in_it = 0; + g_memset(text, 0, 256); + xrdp_list_clear(names); + make_stream(s); + init_stream(s, 8192); + len = g_file_read(fd, s->data, 8192); + if (len > 0) + { + s->end = s->p + len; + for (index = 0; index < len; index++) + { + in_uint8(s, c); + if (c == '[') + in_it = 1; + else if (c == ']') + { + xrdp_list_add_item(names, (int)g_strdup(text)); + in_it = 0; + in_it_index = 0; + g_memset(text, 0, 256); + } + else if (in_it) + { + text[in_it_index] = c; + in_it_index++; + } + } + } + free_stream(s); + return 0; +} + +/*****************************************************************************/ +int xrdp_file_read_line(struct stream* s, char* text) +{ + int i; + char c; + char* hold; + + if (!s_check(s)) + return 1; + hold = s->p; + i = 0; + in_uint8(s, c); + while (c != 10 && c != 13 && s_check(s)) + { + text[i] = c; + i++; + in_uint8(s, c); + } + if (c == 10 || c == 13) + { + while ((c == 10 || c == 13) && s_check(s)) + { + in_uint8(s, c); + } + s->p--; + } + text[i] = 0; + if (text[0] == '[') + { + s->p = hold; + return 1; + } + if (g_strlen(text) > 0) + return 0; + else + return 1; +} + +/*****************************************************************************/ +int xrdp_file_split_name_value(char* text, char* name, char* value) +{ + int len; + int i; + int value_index; + int name_index; + int on_to; + + value_index = 0; + name_index = 0; + on_to = 0; + name[0] = 0; + value[0] = 0; + len = g_strlen(text); + for (i = 0; i < len; i++) + { + if (text[i] == '=') + on_to = 1; + else if (on_to) + { + value[value_index] = text[i]; + value_index++; + value[value_index] = 0; + } + else + { + name[name_index] = text[i]; + name_index++; + name[name_index] = 0; + } + } + return 0; +} + +/*****************************************************************************/ +int xrdp_file_read_section(int fd, char* section, struct xrdp_list* names, + struct xrdp_list* values) +{ + struct stream* s; + char text[256]; + char name[256]; + char value[256]; + char c; + int in_it; + int in_it_index; + int len; + int index; + + g_file_seek(fd, 0); + in_it_index = 0; + in_it = 0; + g_memset(text, 0, 256); + xrdp_list_clear(names); + xrdp_list_clear(values); + make_stream(s); + init_stream(s, 8192); + len = g_file_read(fd, s->data, 8192); + if (len > 0) + { + s->end = s->p + len; + for (index = 0; index < len; index++) + { + in_uint8(s, c); + if (c == '[') + in_it = 1; + else if (c == ']') + { + if (g_strcmp(section, text) == 0) + { + xrdp_file_read_line(s, text); + while (xrdp_file_read_line(s, text) == 0) + { + xrdp_file_split_name_value(text, name, value); + xrdp_list_add_item(names, (int)g_strdup(name)); + xrdp_list_add_item(values, (int)g_strdup(value)); + } + free_stream(s); + return 0; + } + in_it = 0; + in_it_index = 0; + g_memset(text, 0, 256); + } + else if (in_it) + { + text[in_it_index] = c; + in_it_index++; + } + } + } + free_stream(s); + return 0; +} diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c new file mode 100644 index 00000000..b6d873ac --- /dev/null +++ b/xrdp/xrdp_login_wnd.c @@ -0,0 +1,614 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2004 + + main login window and login help window + +*/ + +#include "xrdp.h" + +/*****************************************************************************/ +/* all login help screen events go here */ +int xrdp_wm_login_help_notify(struct xrdp_bitmap* wnd, + struct xrdp_bitmap* sender, + int msg, int param1, int param2) +{ + struct xrdp_painter* p; + + if (wnd == 0) + return 0; + if (sender == 0) + return 0; + if (wnd->owner == 0) + return 0; + if (msg == 1) /* click */ + { + if (sender->id == 1) /* ok button */ + { + if (sender->owner->notify != 0) + { + wnd->owner->notify(wnd->owner, wnd, 100, 1, 0); /* ok */ + } + } + } + else if (msg == WM_PAINT) /* 3 */ + { + p = (struct xrdp_painter*)param1; + if (p != 0) + { + p->font->color = wnd->wm->black; + xrdp_painter_draw_text(p, wnd, 10, 30, "You must be authenticated \ +before using this"); + xrdp_painter_draw_text(p, wnd, 10, 46, "session."); + xrdp_painter_draw_text(p, wnd, 10, 78, "Enter a valid username in \ +the username edit box."); + xrdp_painter_draw_text(p, wnd, 10, 94, "Enter the password in \ +the password edit box."); + xrdp_painter_draw_text(p, wnd, 10, 110, "Both the username and \ +password are case"); + xrdp_painter_draw_text(p, wnd, 10, 126, "sensitive."); + xrdp_painter_draw_text(p, wnd, 10, 158, "Contact your system \ +administrator if you are"); + xrdp_painter_draw_text(p, wnd, 10, 174, "having problems \ +logging on."); + } + } + return 0; +} + +/*****************************************************************************/ +int server_begin_update(int handle) +{ + struct xrdp_mod* mod; + struct xrdp_wm* wm; + struct xrdp_painter* p; + + mod = (struct xrdp_mod*)handle; + wm = (struct xrdp_wm*)mod->wm; + p = xrdp_painter_create(wm); + xrdp_painter_begin_update(p); + mod->painter = (int)p; + return 0; +} + +/*****************************************************************************/ +int server_end_update(int handle) +{ + struct xrdp_mod* mod; + struct xrdp_painter* p; + + mod = (struct xrdp_mod*)handle; + p = (struct xrdp_painter*)mod->painter; + xrdp_painter_end_update(p); + xrdp_painter_delete(p); + mod->painter = 0; + return 0; +} + +/*****************************************************************************/ +int server_fill_rect(int handle, int x, int y, int cx, int cy, + int color) +{ + struct xrdp_mod* mod; + struct xrdp_wm* wm; + struct xrdp_painter* p; + + mod = (struct xrdp_mod*)handle; + wm = (struct xrdp_wm*)mod->wm; + p = (struct xrdp_painter*)mod->painter; + p->fg_color = color; + xrdp_painter_fill_rect(p, wm->screen, x, y, cx, cy); + return 0; +} + +/*****************************************************************************/ +int server_screen_blt(int handle, int x, int y, int cx, int cy, + int srcx, int srcy) +{ + struct xrdp_mod* mod; + struct xrdp_wm* wm; + + mod = (struct xrdp_mod*)handle; + wm = (struct xrdp_wm*)mod->wm; + xrdp_orders_init(wm->orders); + xrdp_orders_screen_blt(wm->orders, x, y, cx, cy, srcx, srcy, 0xcc, 0); + xrdp_orders_send(wm->orders); + return 0; +} + +/*****************************************************************************/ +int server_paint_rect(int handle, int x, int y, int cx, int cy, + char* data) +{ + struct xrdp_mod* mod; + struct xrdp_wm* wm; + struct xrdp_bitmap* b; + + mod = (struct xrdp_mod*)handle; + wm = (struct xrdp_wm*)mod->wm; + b = xrdp_bitmap_create_with_data(cx, cy, wm->screen->bpp, data); + xrdp_wm_send_bitmap(wm, b, x, y, cx, cy); + /*xrdp_painter_draw_bitmap((struct xrdp_painter*)mod->painter, + wm->screen, b, x, y, cx, cy);*/ + xrdp_bitmap_delete(b); + return 0; +} + +/*****************************************************************************/ +int server_set_cursor(int handle, int x, int y, char* data, char* mask) +{ + struct xrdp_mod* mod; + struct xrdp_wm* wm; + + mod = (struct xrdp_mod*)handle; + wm = (struct xrdp_wm*)mod->wm; + xrdp_wm_send_cursor(wm, 2, data, mask, x, y); + return 0; +} + +/*****************************************************************************/ +int server_palette(int handle, int* palette) +{ + struct xrdp_mod* mod; + struct xrdp_wm* wm; + + mod = (struct xrdp_mod*)handle; + wm = (struct xrdp_wm*)mod->wm; + g_memcpy(wm->palette, palette, 256 * sizeof(int)); + xrdp_cache_add_palette(wm->cache, palette); + return 0; +} + +/*****************************************************************************/ +int xrdp_wm_popup_notify(struct xrdp_bitmap* wnd, + struct xrdp_bitmap* sender, + int msg, int param1, int param2) +{ + return 0; +} + +/*****************************************************************************/ +int server_error_popup(int handle, char* error, char* caption) +{ +#ifdef aa0 + struct xrdp_mod* mod; + struct xrdp_wm* wm; + struct xrdp_bitmap* wnd; + struct xrdp_bitmap* but; + + mod = (struct xrdp_mod*)handle; + wm = (struct xrdp_wm*)mod->wm; + wnd = xrdp_bitmap_create(400, 200, wm->screen->bpp, WND_TYPE_WND); + xrdp_list_add_item(wm->screen->child_list, (int)wnd); + wnd->parent = wm->screen; + wnd->owner = wm->screen; + wnd->wm = wm; + wnd->bg_color = wm->grey; + wnd->left = wm->screen->width / 2 - wnd->width / 2; + wnd->top = wm->screen->height / 2 - wnd->height / 2; + wnd->notify = xrdp_wm_popup_notify; + g_strcpy(wnd->caption, caption); + + /* button */ + but = xrdp_bitmap_create(60, 25, wm->screen->bpp, WND_TYPE_BUTTON); + xrdp_list_add_item(wnd->child_list, (int)but); + but->parent = wnd; + but->owner = wnd; + but->wm = wm; + but->left = 180; + but->top = 160; + but->id = 1; + g_strcpy(but->caption, "OK"); + but->tab_stop = 1; + + xrdp_bitmap_invalidate(wm->screen, 0); + //xrdp_bitmap_invalidate(wnd, 0); + g_sleep(2000); +#endif + return 0; +} + +/*****************************************************************************/ +int xrdp_wm_setup_mod(struct xrdp_wm* self, + struct xrdp_mod_data* mod_data) +{ + if (self != 0) + { + if (self->mod_handle == 0) + { + self->mod_handle = g_load_library(mod_data->lib); + if (self->mod_handle != 0) + { + (void*)self->mod_init = + g_get_proc_address(self->mod_handle, "mod_init"); + (void*)self->mod_exit = + g_get_proc_address(self->mod_handle, "mod_exit"); + if (self->mod_init != 0 && self->mod_exit != 0) + { + self->mod = (struct xrdp_mod*)self->mod_init(); + } + } + if (self->mod != 0) + { + self->mod->wm = (int)self; + self->mod->server_begin_update = server_begin_update; + self->mod->server_end_update = server_end_update; + self->mod->server_fill_rect = server_fill_rect; + self->mod->server_screen_blt = server_screen_blt; + self->mod->server_paint_rect = server_paint_rect; + self->mod->server_set_cursor = server_set_cursor; + self->mod->server_palette = server_palette; + self->mod->server_error_popup= server_error_popup; + } + } + } + return 0; +} + +/*****************************************************************************/ +int xrdp_wm_delete_all_childs(struct xrdp_wm* self) +{ + int i; + struct xrdp_bitmap* b; + + for (i = self->screen->child_list->count - 1; i >= 0; i--) + { + b = (struct xrdp_bitmap*)xrdp_list_get_item(self->screen->child_list, i); + xrdp_bitmap_delete(b); + } + xrdp_bitmap_invalidate(self->screen, 0); + return 0; +} + +/*****************************************************************************/ +/* all login screen events go here */ +int xrdp_wm_login_notify(struct xrdp_bitmap* wnd, + struct xrdp_bitmap* sender, + int msg, int param1, int param2) +{ + struct xrdp_bitmap* help; + struct xrdp_bitmap* but; + struct xrdp_bitmap* b; + struct xrdp_bitmap* combo; + struct xrdp_wm* wm; + struct xrdp_rect rect; + struct xrdp_mod_data con_mod; + struct xrdp_mod_data* mod; + int i; + + if (wnd->modal_dialog != 0 && msg != 100) + { + return 0; + } + wm = wnd->wm; + if (msg == 1) /* click */ + { + if (sender->id == 1) /* help button */ + { + /* create help screen */ + help = xrdp_bitmap_create(300, 300, wnd->wm->screen->bpp, 1); + xrdp_list_insert_item(wnd->wm->screen->child_list, 0, (int)help); + help->parent = wnd->wm->screen; + help->owner = wnd; + wnd->modal_dialog = help; + help->wm = wnd->wm; + help->bg_color = wnd->wm->grey; + help->left = wnd->wm->screen->width / 2 - help->width / 2; + help->top = wnd->wm->screen->height / 2 - help->height / 2; + help->notify = xrdp_wm_login_help_notify; + g_strcpy(help->caption, "Login help"); + /* ok button */ + but = xrdp_bitmap_create(60, 25, wnd->wm->screen->bpp, 3); + xrdp_list_insert_item(help->child_list, 0, (int)but); + but->parent = help; + but->owner = help; + but->wm = wnd->wm; + but->left = 120; + but->top = 260; + but->id = 1; + but->tab_stop = 1; + g_strcpy(but->caption, "OK"); + /* draw it */ + help->focused_control = but; + //wnd->wm->focused_window = help; + xrdp_bitmap_invalidate(help, 0); + xrdp_wm_set_focused(wnd->wm, help); + //xrdp_bitmap_invalidate(wnd->focused_control, 0); + } + else if (sender->id == 2) /* cancel button */ + { + /*if (wnd != 0) + if (wnd->wm != 0) + if (wnd->wm->pro_layer != 0) + wnd->wm->pro_layer->term = 1;*/ + } + else if (sender->id == 3) /* ok button */ + { + combo = (struct xrdp_bitmap*)xrdp_bitmap_get_child_by_id(wnd, 6); + if (combo != 0) + { + mod = (struct xrdp_mod_data*)xrdp_list_get_item(combo->data_list, + combo->item_index); + if (mod != 0) + { + con_mod = *mod; + if (xrdp_wm_setup_mod(wm, mod) == 0) + { + xrdp_wm_delete_all_childs(wm); + if (!wm->pro_layer->term) + { + if (wm->mod->mod_start((int)wm->mod, wm->screen->width, + wm->screen->height, wm->screen->bpp) != 0) + wm->pro_layer->term = 1; /* kill session */ + } + if (!wm->pro_layer->term) + { + if (wm->mod->mod_connect((int)wm->mod, con_mod.ip, con_mod.port, + con_mod.user, con_mod.password) != 0) + wm->pro_layer->term = 1; /* kill session */ + } + if (!wm->pro_layer->term) + { + if (wm->mod->sck != 0) + wm->pro_layer->app_sck = wm->mod->sck; + } + } + } + } + } + } + else if (msg == 2) /* mouse move */ + { + } + else if (msg == 100) /* modal result is done */ + { + i = xrdp_list_index_of(wnd->wm->screen->child_list, (int)sender); + if (i >= 0) + { + b = (struct xrdp_bitmap*) + xrdp_list_get_item(wnd->wm->screen->child_list, i); + xrdp_list_remove_item(sender->wm->screen->child_list, i); + MAKERECT(rect, b->left, b->top, b->width, b->height); + xrdp_bitmap_invalidate(wnd->wm->screen, &rect); + xrdp_bitmap_delete(sender); + wnd->modal_dialog = 0; + xrdp_wm_set_focused(wnd->wm, wnd); + } + } + return 0; +} + +/******************************************************************************/ +int xrdp_wm_login_fill_in_combo(struct xrdp_wm* self, struct xrdp_bitmap* b) +{ + struct xrdp_list* sections; + struct xrdp_list* section_names; + struct xrdp_list* section_values; + int fd; + int i; + int j; + char* p; + char* q; + char* r; + struct xrdp_mod_data* mod_data; + + sections = xrdp_list_create(); + sections->auto_free = 1; + section_names = xrdp_list_create(); + section_names->auto_free = 1; + section_values = xrdp_list_create(); + section_values->auto_free = 1; + fd = g_file_open("xrdp.ini"); + xrdp_file_read_sections(fd, sections); + for (i = 0; i < sections->count; i++) + { + p = (char*)xrdp_list_get_item(sections, i); + xrdp_file_read_section(fd, p, section_names, section_values); + if (g_strcmp(p, "globals") == 0) + { + } + else + { + mod_data = g_malloc(sizeof(struct xrdp_mod_data), 1); + g_strcpy(mod_data->name, p); + for (j = 0; j < section_names->count; j++) + { + q = (char*)xrdp_list_get_item(section_names, j); + r = (char*)xrdp_list_get_item(section_values, j); + if (g_strcmp("name", q) == 0) + { + g_strcpy(mod_data->name, r); + } + else if (g_strcmp("lib", q) == 0) + { + g_strcpy(mod_data->lib, r); + } + else if (g_strcmp("ip", q) == 0) + { + g_strcpy(mod_data->ip, r); + } + else if (g_strcmp("port", q) == 0) + { + g_strcpy(mod_data->port, r); + } + else if (g_strcmp("user", q) == 0) + { + g_strcpy(mod_data->user, r); + } + else if (g_strcmp("password", q) == 0) + { + g_strcpy(mod_data->password, r); + } + } + xrdp_list_add_item(b->string_list, (int)g_strdup(mod_data->name)); + xrdp_list_add_item(b->data_list, (int)mod_data); + } + } + g_file_close(fd); + xrdp_list_delete(sections); + xrdp_list_delete(section_names); + xrdp_list_delete(section_values); + return 0; +} + +/******************************************************************************/ +int xrdp_login_wnd_create(struct xrdp_wm* self) +{ + struct xrdp_bitmap* but; + + /* draw login window */ + self->login_window = xrdp_bitmap_create(400, 200, self->screen->bpp, + WND_TYPE_WND); + xrdp_list_add_item(self->screen->child_list, (int)self->login_window); + self->login_window->parent = self->screen; + self->login_window->owner = self->screen; + self->login_window->wm = self; + self->login_window->bg_color = self->grey; + self->login_window->left = self->screen->width / 2 - + self->login_window->width / 2; + self->login_window->top = self->screen->height / 2 - + self->login_window->height / 2; + self->login_window->notify = xrdp_wm_login_notify; + g_strcpy(self->login_window->caption, "Login to xrdp"); + + /* image */ + but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE); + xrdp_bitmap_load(but, "xrdp256.bmp", self->palette); + but->parent = self->screen; + but->owner = self->screen; + but->wm = self; + but->left = self->screen->width - but->width; + but->top = self->screen->height - but->height; + xrdp_list_add_item(self->screen->child_list, (int)but); + + /* image */ + but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE); + xrdp_bitmap_load(but, "ad256.bmp", self->palette); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 10; + but->top = 30; + xrdp_list_add_item(self->login_window->child_list, (int)but); + + /* label */ + but = xrdp_bitmap_create(60, 20, self->screen->bpp, WND_TYPE_LABEL); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 155; + but->top = 50; + g_strcpy(but->caption, "Username"); + + /* edit */ + but = xrdp_bitmap_create(140, 20, self->screen->bpp, WND_TYPE_EDIT); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 220; + but->top = 50; + but->id = 4; + but->cursor = 1; + but->tab_stop = 1; + self->login_window->focused_control = but; + + /* label */ + but = xrdp_bitmap_create(60, 20, self->screen->bpp, WND_TYPE_LABEL); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 155; + but->top = 80; + g_strcpy(but->caption, "Password"); + + /* edit */ + but = xrdp_bitmap_create(140, 20, self->screen->bpp, WND_TYPE_EDIT); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 220; + but->top = 80; + but->id = 5; + but->cursor = 1; + but->tab_stop = 1; + but->password_char = '*'; + + /* label */ + but = xrdp_bitmap_create(60, 20, self->screen->bpp, WND_TYPE_LABEL); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 155; + but->top = 110; + g_strcpy(but->caption, "Module"); + + /* combo */ + but = xrdp_bitmap_create(140, 20, self->screen->bpp, WND_TYPE_COMBO); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 220; + but->top = 110; + but->id = 6; + but->tab_stop = 1; + xrdp_wm_login_fill_in_combo(self, but); + + /* button */ + but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 180; + but->top = 160; + but->id = 3; + g_strcpy(but->caption, "OK"); + but->tab_stop = 1; + + /* button */ + but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 250; + but->top = 160; + but->id = 2; + g_strcpy(but->caption, "Cancel"); + but->tab_stop = 1; + + /* button */ + but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON); + xrdp_list_add_item(self->login_window->child_list, (int)but); + but->parent = self->login_window; + but->owner = self->login_window; + but->wm = self; + but->left = 320; + but->top = 160; + but->id = 1; + g_strcpy(but->caption, "Help"); + but->tab_stop = 1; + + return 0; +} diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c index b3508fff..6a69e5f3 100644 --- a/xrdp/xrdp_painter.c +++ b/xrdp/xrdp_painter.c @@ -32,6 +32,7 @@ struct xrdp_painter* xrdp_painter_create(struct xrdp_wm* wm) self->orders = wm->orders; self->rop = 0xcc; /* copy */ self->font = xrdp_font_create(wm); + self->clip_children = 1; return self; } @@ -155,7 +156,8 @@ int xrdp_painter_fill_rect(struct xrdp_painter* self, if (bitmap->type == WND_TYPE_BITMAP) /* 0 */ return 0; region = xrdp_region_create(self->wm); - xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region); + xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region, + self->clip_children); i = 0; while (xrdp_region_get_rect(region, i, &rect) == 0) { @@ -192,11 +194,12 @@ int xrdp_painter_fill_rect2(struct xrdp_painter* self, return 0; /* todo data */ - + if (bitmap->type == WND_TYPE_BITMAP) /* 0 */ return 0; region = xrdp_region_create(self->wm); - xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region); + xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region, + self->clip_children); i = 0; while (xrdp_region_get_rect(region, i, &rect) == 0) { @@ -250,7 +253,8 @@ int xrdp_painter_draw_bitmap(struct xrdp_painter* self, if (bitmap->type == WND_TYPE_BITMAP) return 0; region = xrdp_region_create(self->wm); - xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region); + xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region, + self->clip_children); b = bitmap; while (b != 0) { @@ -424,7 +428,7 @@ int xrdp_painter_draw_text(struct xrdp_painter* self, } region = xrdp_region_create(self->wm); xrdp_wm_get_vis_region(self->wm, bitmap, x, y, total_width, total_height, - region); + region, self->clip_children); b = bitmap; while (b != 0) { diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c index f488cdbe..0f8323da 100644 --- a/xrdp/xrdp_process.c +++ b/xrdp/xrdp_process.c @@ -36,7 +36,9 @@ struct xrdp_process* xrdp_process_create(struct xrdp_listen* owner) void xrdp_process_delete(struct xrdp_process* self) { if (self == 0) + { return; + } xrdp_rdp_delete(self->rdp_layer); xrdp_orders_delete(self->orders); xrdp_wm_delete(self->wm); @@ -60,14 +62,16 @@ int xrdp_process_main_loop(struct xrdp_process* self) while (!g_is_term() && !self->term) { i = g_tcp_select(self->sck, self->app_sck); - if (i == 1) + if (i & 1) { init_stream(s, 8192); cont = 1; while (cont) { if (xrdp_rdp_recv(self->rdp_layer, s, &code) != 0) + { break; + } DEBUG(("xrdp_process_main_loop code %d\n\r", code)); switch (code) { @@ -76,11 +80,11 @@ int xrdp_process_main_loop(struct xrdp_process* self) break; case 0: break; - case RDP_PDU_CONFIRM_ACTIVE: - xrdp_rdp_process_confirm_active(self->rdp_layer, s); /* 3 */ + case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ + xrdp_rdp_process_confirm_active(self->rdp_layer, s); break; - case RDP_PDU_DATA: - if (xrdp_rdp_process_data(self->rdp_layer, s) != 0) /* 7 */ + case RDP_PDU_DATA: /* 7 */ + if (xrdp_rdp_process_data(self->rdp_layer, s) != 0) { DEBUG(("xrdp_rdp_process_data returned non zero\n\r")); cont = 0; @@ -92,10 +96,14 @@ int xrdp_process_main_loop(struct xrdp_process* self) break; } if (cont) + { cont = s->next_packet < s->end; + } } if (cont) /* we must have errored out */ + { break; + } if (self->rdp_layer->up_and_running && self->wm == 0) { /* only do this once */ @@ -105,13 +113,29 @@ int xrdp_process_main_loop(struct xrdp_process* self) xrdp_wm_init(self->wm); } } - else if (i == 2) + if (i & 2) /* mod socket fired */ { + if (self->wm->mod == 0) + { + break; + } + if (self->wm->mod->mod_signal == 0) + { + break; + } + if (self->wm->mod->mod_signal((int)self->wm->mod) != 0) + { + break; + } } - else if (i == 0) + if (i == 0) /* no data on any stream */ + { g_sleep(10); - else + } + else if (i < 0) + { break; + } } } xrdp_rdp_disconnect(self->rdp_layer); diff --git a/xrdp/xrdp_rdp.c b/xrdp/xrdp_rdp.c index 6c9a3bfc..08c446aa 100644 --- a/xrdp/xrdp_rdp.c +++ b/xrdp/xrdp_rdp.c @@ -403,7 +403,9 @@ int xrdp_rdp_process_input_mouse(struct xrdp_rdp* self, int device_flags, if (!self->up_and_running) return 0; if (device_flags & MOUSE_FLAG_MOVE) /* 0x0800 */ + { xrdp_wm_mouse_move(self->pro_layer->wm, x, y); + } if (device_flags & MOUSE_FLAG_BUTTON1) /* 0x1000 */ { if (device_flags & MOUSE_FLAG_DOWN) /* 0x8000 */ @@ -418,6 +420,23 @@ int xrdp_rdp_process_input_mouse(struct xrdp_rdp* self, int device_flags, else xrdp_wm_mouse_click(self->pro_layer->wm, x, y, 2, 0); } + if (device_flags & MOUSE_FLAG_BUTTON3) /* 0x4000 */ + { + if (device_flags & MOUSE_FLAG_DOWN) /* 0x8000 */ + xrdp_wm_mouse_click(self->pro_layer->wm, x, y, 3, 1); + else + xrdp_wm_mouse_click(self->pro_layer->wm, x, y, 3, 0); + } + if (device_flags == MOUSE_FLAG_BUTTON4 || /* 0x0280 */ + device_flags == 0x0278) + { + xrdp_wm_mouse_click(self->pro_layer->wm, 0, 0, 4, 0); + } + if (device_flags == MOUSE_FLAG_BUTTON5 || /* 0x0380 */ + device_flags == 0x0388) + { + xrdp_wm_mouse_click(self->pro_layer->wm, 0, 0, 5, 0); + } return 0; } @@ -541,6 +560,8 @@ int xrdp_rdp_process_screen_update(struct xrdp_rdp* self, struct stream* s) int top; int right; int bottom; + int cx; + int cy; struct xrdp_rect rect; in_uint32_le(s, op); @@ -548,9 +569,13 @@ int xrdp_rdp_process_screen_update(struct xrdp_rdp* self, struct stream* s) in_uint16_le(s, top); in_uint16_le(s, right); in_uint16_le(s, bottom); - MAKERECT(rect, left, top, (right - left) + 1, (bottom - top) + 1); + cx = (right - left) + 1; + cy = (bottom - top) + 1; if (self->up_and_running && self->pro_layer->wm != 0) + { + MAKERECT(rect, left, top, cx, cy); xrdp_bitmap_invalidate(self->pro_layer->wm->screen, &rect); + } return 0; } diff --git a/xrdp/xrdp_tcp.c b/xrdp/xrdp_tcp.c index 23ff2338..fd263dfc 100644 --- a/xrdp/xrdp_tcp.c +++ b/xrdp/xrdp_tcp.c @@ -60,12 +60,16 @@ int xrdp_tcp_recv(struct xrdp_tcp* self, struct stream* s, int len) while (len > 0) { if (g_is_term()) + { return 1; + } rcvd = g_tcp_recv(self->sck, s->end, len, 0); if (rcvd == -1) { if (g_tcp_last_error_would_block(self->sck)) + { g_sleep(1); + } else { DEBUG((" error = -1 in xrdp_tcp_recv socket %d\n", self->sck)) diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index bf80cb92..4527533c 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -20,6 +20,38 @@ */ +/* lib */ +struct xrdp_mod +{ + int size; /* size of this struct */ + /* client functions */ + int (*mod_start)(int handle, int w, int h, int bpp); + int (*mod_connect)(int handle, char* ip, char* port, + char* username, char* password); + int (*mod_event)(int handle, int msg, int param1, int param2); + int (*mod_signal)(int handle); + int (*mod_invalidate)(int handle, int x, int y, int cx, int cy); + int d1[95]; + /* server functions */ + int (*server_begin_update)(int handle); + int (*server_end_update)(int handle); + int (*server_fill_rect)(int handle, int x, int y, int cx, int cy, + int color); + int (*server_screen_blt)(int handle, int x, int y, int cx, int cy, + int srcx, int srcy); + int (*server_paint_rect)(int handle, int x, int y, int cx, int cy, + char* data); + int (*server_set_cursor)(int handle, int x, int y, char* data, char* mask); + int (*server_palette)(int handle, int* palette); + int (*server_error_popup)(int handle, char* error, char* caption); + int d2[92]; + /* common */ + int handle; /* pointer to self as int */ + int wm; /* struct xrdp_wm* */ + int painter; + int sck; +}; + /* for memory debugging */ struct xrdp_mem { @@ -318,11 +350,18 @@ struct xrdp_wm struct xrdp_bitmap* focused_window; /* cursor */ int current_cursor; + int mouse_x; + int mouse_y; /* keyboard info */ int keys[256]; /* key states 0 up 1 down*/ int caps_lock; int scroll_lock; int num_lock; + /* mod vars */ + int mod_handle; + int (*mod_init)(); + int (*mod_exit)(int); + struct xrdp_mod* mod; }; /* rdp process */ @@ -363,6 +402,7 @@ struct xrdp_painter int rop; int use_clip; struct xrdp_rect clip; + int clip_children; int bg_color; int fg_color; struct xrdp_brush brush; @@ -387,6 +427,7 @@ struct xrdp_bitmap /* for bitmap */ int bpp; int line_size; /* in bytes */ + int do_not_free_data; char* data; /* for all but bitmap */ int left; @@ -409,6 +450,7 @@ struct xrdp_bitmap int state; /* for button 0 = normal 1 = down */ /* for combo */ struct xrdp_list* string_list; + struct xrdp_list* data_list; /* for combo or popup */ int item_index; /* for popup */ @@ -426,3 +468,14 @@ struct xrdp_font int size; int style; }; + +/* modual */ +struct xrdp_mod_data +{ + char name[256]; + char lib[256]; + char ip[256]; + char port[256]; + char user[256]; + char password[256]; +}; diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 904445dc..f2ab6f64 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -48,6 +48,12 @@ void xrdp_wm_delete(struct xrdp_wm* self) xrdp_cache_delete(self->cache); xrdp_painter_delete(self->painter); xrdp_bitmap_delete(self->screen); + /* free any modual stuff */ + if (self->mod != 0 && self->mod_exit != 0) + self->mod_exit((int)self->mod); + if (self->mod_handle != 0) + g_free_library(self->mod_handle); + /* free self */ g_free(self); } @@ -79,102 +85,66 @@ int xrdp_wm_send_palette(struct xrdp_wm* self) } /*****************************************************************************/ -/* todo */ int xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap, int x, int y, int cx, int cy) { int data_size; int line_size; int i; + int j; int total_lines; int lines_sending; + int Bpp; + int e; char* p; + char* q; struct stream* s; + lines_sending = 0; make_stream(s); init_stream(s, 8192); - data_size = bitmap->width * bitmap->height * ((bitmap->bpp + 7) / 8); - line_size = bitmap->width * ((bitmap->bpp + 7) / 8); - total_lines = data_size / line_size; + Bpp = (bitmap->bpp + 7) / 8; + data_size = bitmap->width * bitmap->height * Bpp; + line_size = bitmap->width * Bpp; + total_lines = bitmap->height; + e = bitmap->width % 4; + if (e != 0) + e = 4 - e; i = 0; p = bitmap->data; - lines_sending = 4096 / line_size; - if (lines_sending > total_lines) - lines_sending = total_lines; - while (i < total_lines) + if (line_size > 0 && total_lines > 0) { - xrdp_rdp_init_data(self->rdp_layer, s); - out_uint16_le(s, RDP_UPDATE_BITMAP); - out_uint16_le(s, 1); /* num updates */ - out_uint16_le(s, x); - out_uint16_le(s, y + i); - out_uint16_le(s, (x + cx) - 1); - out_uint16_le(s, (y + i + cy) - 1); - out_uint16_le(s, bitmap->width); - out_uint16_le(s, lines_sending); - out_uint16_le(s, bitmap->bpp); /* bpp */ - out_uint16_le(s, 0); /* compress */ - out_uint16_le(s, line_size * lines_sending); /* bufsize */ - out_uint8a(s, p, line_size * lines_sending); - s_mark_end(s); - xrdp_rdp_send_data(self->rdp_layer, s, RDP_DATA_PDU_UPDATE); - p = p + line_size * lines_sending; - i = i + lines_sending; - if (i + lines_sending > total_lines) - lines_sending = total_lines - i; - if (lines_sending <= 0) - break; - } - free_stream(s); - return 0; -} - -/*****************************************************************************/ -/* all login help screen events go here */ -int xrdp_wm_login_help_notify(struct xrdp_bitmap* wnd, - struct xrdp_bitmap* sender, - int msg, int param1, int param2) -{ - struct xrdp_painter* p; - - if (wnd == 0) - return 0; - if (sender == 0) - return 0; - if (wnd->owner == 0) - return 0; - if (msg == 1) /* click */ - { - if (sender->id == 1) /* ok button */ + while (i < total_lines) { - if (sender->owner->notify != 0) + lines_sending = 4096 / (line_size + e * Bpp); + if (i + lines_sending > total_lines) + lines_sending = total_lines - i; + p = p + line_size * lines_sending; + xrdp_rdp_init_data(self->rdp_layer, s); + out_uint16_le(s, RDP_UPDATE_BITMAP); + out_uint16_le(s, 1); /* num updates */ + out_uint16_le(s, x); + out_uint16_le(s, y + i); + out_uint16_le(s, (x + cx) - 1); + out_uint16_le(s, (y + i + lines_sending) - 1); + out_uint16_le(s, bitmap->width + e); + out_uint16_le(s, lines_sending); + out_uint16_le(s, bitmap->bpp); /* bpp */ + out_uint16_le(s, 0); /* compress */ + out_uint16_le(s, (line_size + e * Bpp) * lines_sending); /* bufsize */ + q = p; + for (j = 0; j < lines_sending; j++) { - wnd->owner->notify(wnd->owner, wnd, 100, 1, 0); /* ok */ + q = q - line_size; + out_uint8a(s, q, line_size) + out_uint8s(s, e * Bpp); } + s_mark_end(s); + xrdp_rdp_send_data(self->rdp_layer, s, RDP_DATA_PDU_UPDATE); + i = i + lines_sending; } } - else if (msg == WM_PAINT) /* 3 */ - { - p = (struct xrdp_painter*)param1; - if (p != 0) - { - p->font->color = wnd->wm->black; - xrdp_painter_draw_text(p, wnd, 10, 30, "You must be authenticated \ -before using this"); - xrdp_painter_draw_text(p, wnd, 10, 46, "session."); - xrdp_painter_draw_text(p, wnd, 10, 78, "Enter a valid username in \ -the username edit box."); - xrdp_painter_draw_text(p, wnd, 10, 94, "Enter the password in \ -the password edit box."); - xrdp_painter_draw_text(p, wnd, 10, 110, "Both the username and \ -password are case"); - xrdp_painter_draw_text(p, wnd, 10, 126, "sensitive."); - xrdp_painter_draw_text(p, wnd, 10, 158, "Contact your system \ -administrator if you are"); - xrdp_painter_draw_text(p, wnd, 10, 174, "having problems \ -logging on."); - } - } + free_stream(s); return 0; } @@ -206,83 +176,6 @@ int xrdp_wm_set_focused(struct xrdp_wm* self, struct xrdp_bitmap* wnd) return 0; } -/*****************************************************************************/ -/* all login screen events go here */ -int xrdp_wm_login_notify(struct xrdp_bitmap* wnd, - struct xrdp_bitmap* sender, - int msg, int param1, int param2) -{ - struct xrdp_bitmap* help; - struct xrdp_bitmap* but; - struct xrdp_bitmap* b; - struct xrdp_rect rect; - int i; - - if (wnd->modal_dialog != 0 && msg != 100) - return 0; - if (msg == 1) /* click */ - { - if (sender->id == 1) /* help button */ - { - /* create help screen */ - help = xrdp_bitmap_create(300, 300, wnd->wm->screen->bpp, 1); - xrdp_list_insert_item(wnd->wm->screen->child_list, 0, (int)help); - help->parent = wnd->wm->screen; - help->owner = wnd; - wnd->modal_dialog = help; - help->wm = wnd->wm; - help->bg_color = wnd->wm->grey; - help->left = wnd->wm->screen->width / 2 - help->width / 2; - help->top = wnd->wm->screen->height / 2 - help->height / 2; - help->notify = xrdp_wm_login_help_notify; - g_strcpy(help->caption, "Logon help"); - /* ok button */ - but = xrdp_bitmap_create(60, 25, wnd->wm->screen->bpp, 3); - xrdp_list_insert_item(help->child_list, 0, (int)but); - but->parent = help; - but->owner = help; - but->wm = wnd->wm; - but->left = 120; - but->top = 260; - but->id = 1; - but->tab_stop = 1; - g_strcpy(but->caption, "OK"); - /* draw it */ - help->focused_control = but; - //wnd->wm->focused_window = help; - xrdp_bitmap_invalidate(help, 0); - xrdp_wm_set_focused(wnd->wm, help); - //xrdp_bitmap_invalidate(wnd->focused_control, 0); - } - else if (sender->id == 2) /* cancel button */ - { - /*if (wnd != 0) - if (wnd->wm != 0) - if (wnd->wm->pro_layer != 0) - wnd->wm->pro_layer->term = 1;*/ - } - } - else if (msg == 2) /* mouse move */ - { - } - else if (msg == 100) /* modal result is done */ - { - i = xrdp_list_index_of(wnd->wm->screen->child_list, (int)sender); - if (i >= 0) - { - b = (struct xrdp_bitmap*) - xrdp_list_get_item(wnd->wm->screen->child_list, i); - xrdp_list_remove_item(sender->wm->screen->child_list, i); - MAKERECT(rect, b->left, b->top, b->width, b->height); - xrdp_bitmap_invalidate(wnd->wm->screen, &rect); - xrdp_bitmap_delete(sender); - wnd->modal_dialog = 0; - xrdp_wm_set_focused(wnd->wm, wnd); - } - } - return 0; -} - /*****************************************************************************/ int xrdp_set_cursor(struct xrdp_wm* self, int cache_idx) { @@ -326,28 +219,20 @@ int xrdp_wm_get_pixel(char* data, int x, int y, int width, int bpp) return 0; } - /*****************************************************************************/ -/* send a cursor from a file */ -int xrdp_send_cursor(struct xrdp_wm* self, char* file_name, int cache_idx) +int xrdp_wm_load_cursor(struct xrdp_wm* self, char* file_name, char* data, + char* mask, int* x, int* y) { int fd; + int bpp; int w; int h; - int x; - int y; - int bpp; int i; int j; - int rv; int pixel; int palette[16]; struct stream* fs; - struct stream* s; - rv = 1; - make_stream(s); - init_stream(s, 8192); make_stream(fs); init_stream(fs, 8192); fd = g_file_open(file_name); @@ -357,23 +242,13 @@ int xrdp_send_cursor(struct xrdp_wm* self, char* file_name, int cache_idx) in_uint8(fs, w); in_uint8(fs, h); in_uint8s(fs, 2); - in_uint16_le(fs, x); - in_uint16_le(fs, y); + in_uint16_le(fs, *x); + in_uint16_le(fs, *y); in_uint8s(fs, 22); in_uint8(fs, bpp); in_uint8s(fs, 25); if (w == 32 && h == 32) { - xrdp_rdp_init_data(self->rdp_layer, s); - out_uint16_le(s, RDP_POINTER_COLOR); - out_uint16_le(s, 0); /* pad */ - out_uint16_le(s, cache_idx); /* cache_idx */ - out_uint16_le(s, x); - out_uint16_le(s, y); - out_uint16_le(s, w); - out_uint16_le(s, h); - out_uint16_le(s, 128); - out_uint16_le(s, 3072); if (bpp == 1) { in_uint8a(fs, palette, 8); @@ -382,9 +257,12 @@ int xrdp_send_cursor(struct xrdp_wm* self, char* file_name, int cache_idx) for (j = 0; j < 32; j++) { pixel = palette[xrdp_wm_get_pixel(fs->p, j, i, 32, 1)]; - out_uint8(s, pixel); - out_uint8(s, pixel >> 8); - out_uint8(s, pixel >> 16); + *data = pixel; + data++; + *data = pixel >> 8; + data++; + *data = pixel >> 16; + data++; } } in_uint8s(fs, 128); @@ -396,28 +274,71 @@ int xrdp_send_cursor(struct xrdp_wm* self, char* file_name, int cache_idx) { for (j = 0; j < 32; j++) { - pixel = palette[xrdp_wm_get_pixel(fs->p, j, i, 32, 4)]; - out_uint8(s, pixel); - out_uint8(s, pixel >> 8); - out_uint8(s, pixel >> 16); + pixel = palette[xrdp_wm_get_pixel(fs->p, j, i, 32, 1)]; + *data = pixel; + data++; + *data = pixel >> 8; + data++; + *data = pixel >> 16; + data++; } } in_uint8s(fs, 512); } - out_uint8a(s, fs->p, 128); /* mask */ - s_mark_end(s); - xrdp_rdp_send_data(self->rdp_layer, s, RDP_DATA_PDU_POINTER); - rv = 0; + g_memcpy(mask, fs->p, 128); /* mask */ } - free_stream(s); free_stream(fs); - return rv; + return 0; +} + +/*****************************************************************************/ +int xrdp_wm_send_cursor(struct xrdp_wm* self, int cache_idx, + char* data, char* mask, int x, int y) +{ + struct stream* s; + char* p; + int i; + int j; + + make_stream(s); + init_stream(s, 8192); + xrdp_rdp_init_data(self->rdp_layer, s); + out_uint16_le(s, RDP_POINTER_COLOR); + out_uint16_le(s, 0); /* pad */ + out_uint16_le(s, cache_idx); /* cache_idx */ + out_uint16_le(s, x); + out_uint16_le(s, y); + out_uint16_le(s, 32); + out_uint16_le(s, 32); + out_uint16_le(s, 128); + out_uint16_le(s, 3072); + p = data; + for (i = 0; i < 32; i++) + { + for (j = 0; j < 32; j++) + { + out_uint8(s, *p); + p++; + out_uint8(s, *p); + p++; + out_uint8(s, *p); + p++; + } + } + out_uint8a(s, mask, 128); /* mask */ + s_mark_end(s); + xrdp_rdp_send_data(self->rdp_layer, s, RDP_DATA_PDU_POINTER); + free_stream(s); + return 0; } /*****************************************************************************/ int xrdp_wm_init(struct xrdp_wm* self) { - struct xrdp_bitmap* but; + char data[32 * (32 * 3)]; + char mask[32 * (32 / 8)]; + int x; + int y; if (self->screen->bpp == 8) { @@ -473,147 +394,8 @@ int xrdp_wm_init(struct xrdp_wm* self) self->red = COLOR24(0xff, 0x00, 0x00); self->green = COLOR24(0x00, 0xff, 0x00); } - /* draw login window */ - self->login_window = xrdp_bitmap_create(400, 200, self->screen->bpp, - WND_TYPE_WND); - xrdp_list_add_item(self->screen->child_list, (int)self->login_window); - self->login_window->parent = self->screen; - self->login_window->owner = self->screen; - self->login_window->wm = self; - self->login_window->bg_color = self->grey; - self->login_window->left = self->screen->width / 2 - - self->login_window->width / 2; - self->login_window->top = self->screen->height / 2 - - self->login_window->height / 2; - self->login_window->notify = xrdp_wm_login_notify; - g_strcpy(self->login_window->caption, "Logon to xrdp"); - - /* image */ - but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE); - xrdp_bitmap_load(but, "xrdp256.bmp", self->palette); - but->parent = self->screen; - but->owner = self->screen; - but->wm = self; - but->left = self->screen->width - but->width; - but->top = self->screen->height - but->height; - xrdp_list_add_item(self->screen->child_list, (int)but); - - /* image */ - but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE); - xrdp_bitmap_load(but, "ad256.bmp", self->palette); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 10; - but->top = 30; - xrdp_list_add_item(self->login_window->child_list, (int)but); - - /* label */ - but = xrdp_bitmap_create(60, 20, self->screen->bpp, WND_TYPE_LABEL); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 155; - but->top = 50; - g_strcpy(but->caption, "Username"); - - /* edit */ - but = xrdp_bitmap_create(140, 20, self->screen->bpp, WND_TYPE_EDIT); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 220; - but->top = 50; - but->id = 4; - but->cursor = 1; - but->tab_stop = 1; - self->login_window->focused_control = but; - /* label */ - but = xrdp_bitmap_create(60, 20, self->screen->bpp, WND_TYPE_LABEL); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 155; - but->top = 80; - g_strcpy(but->caption, "Password"); - - /* edit */ - but = xrdp_bitmap_create(140, 20, self->screen->bpp, WND_TYPE_EDIT); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 220; - but->top = 80; - but->id = 5; - but->cursor = 1; - but->tab_stop = 1; - but->password_char = '*'; - - /* label */ - but = xrdp_bitmap_create(60, 20, self->screen->bpp, WND_TYPE_LABEL); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 155; - but->top = 110; - g_strcpy(but->caption, "Module"); - - /* combo */ - but = xrdp_bitmap_create(140, 20, self->screen->bpp, WND_TYPE_COMBO); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 220; - but->top = 110; - but->id = 6; - but->tab_stop = 1; - xrdp_list_add_item(but->string_list, (int)g_strdup("Test")); - xrdp_list_add_item(but->string_list, (int)g_strdup("VNC")); - xrdp_list_add_item(but->string_list, (int)g_strdup("X11")); - xrdp_list_add_item(but->string_list, (int)g_strdup("Console")); - - /* button */ - but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 180; - but->top = 160; - but->id = 3; - g_strcpy(but->caption, "OK"); - but->tab_stop = 1; - - /* button */ - but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 250; - but->top = 160; - but->id = 2; - g_strcpy(but->caption, "Cancel"); - but->tab_stop = 1; - - /* button */ - but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON); - xrdp_list_add_item(self->login_window->child_list, (int)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->wm = self; - but->left = 320; - but->top = 160; - but->id = 1; - g_strcpy(but->caption, "Help"); - but->tab_stop = 1; + xrdp_login_wnd_create(self); /* clear screen */ self->screen->bg_color = self->black; @@ -621,8 +403,10 @@ int xrdp_wm_init(struct xrdp_wm* self) xrdp_wm_set_focused(self, self->login_window); - xrdp_send_cursor(self, "cursor1.cur", 1); - xrdp_send_cursor(self, "cursor0.cur", 0); + xrdp_wm_load_cursor(self, "cursor1.cur", data, mask, &x, &y); + xrdp_wm_send_cursor(self, 1, data, mask, x, y); + xrdp_wm_load_cursor(self, "cursor0.cur", data, mask, &x, &y); + xrdp_wm_send_cursor(self, 0, data, mask, x, y); return 0; } @@ -632,7 +416,7 @@ int xrdp_wm_init(struct xrdp_wm* self) /* putting the rects in region */ int xrdp_wm_get_vis_region(struct xrdp_wm* self, struct xrdp_bitmap* bitmap, int x, int y, int cx, int cy, - struct xrdp_region* region) + struct xrdp_region* region, int clip_children) { int i; struct xrdp_bitmap* p; @@ -652,16 +436,17 @@ int xrdp_wm_get_vis_region(struct xrdp_wm* self, struct xrdp_bitmap* bitmap, a.right = MIN(self->screen->left + self->screen->width, a.right); a.bottom = MIN(self->screen->top + self->screen->height, a.bottom); xrdp_region_add_rect(region, &a); - if (bitmap == self->screen) - return 0; - /* loop through all windows in z order */ - for (i = 0; i < self->screen->child_list->count; i++) + if (clip_children) { - p = (struct xrdp_bitmap*)xrdp_list_get_item(self->screen->child_list, i); - if (p == bitmap || p == bitmap->parent) - return 0; - MAKERECT(b, p->left, p->top, p->width, p->height); - xrdp_region_subtract_rect(region, &b); + /* loop through all windows in z order */ + for (i = 0; i < self->screen->child_list->count; i++) + { + p = (struct xrdp_bitmap*)xrdp_list_get_item(self->screen->child_list, i); + if (p == bitmap || p == bitmap->parent) + return 0; + MAKERECT(b, p->left, p->top, p->width, p->height); + xrdp_region_subtract_rect(region, &b); + } } return 0; } @@ -697,6 +482,7 @@ struct xrdp_bitmap* xrdp_wm_at_pos(struct xrdp_bitmap* wnd, int x, int y, /*****************************************************************************/ int xrdp_wm_xor_pat(struct xrdp_wm* self, int x, int y, int cx, int cy) { + self->painter->clip_children = 0; self->painter->rop = 0x5a; xrdp_painter_begin_update(self->painter); self->painter->use_clip = 0; @@ -724,6 +510,7 @@ int xrdp_wm_xor_pat(struct xrdp_wm* self, int x, int y, int cx, int cy) cy - 10); xrdp_painter_end_update(self->painter); self->painter->rop = 0xcc; + self->painter->clip_children = 1; return 0; } @@ -843,7 +630,6 @@ int xrdp_wm_mouse_move(struct xrdp_wm* self, int x, int y) int boxx; int boxy; - DEBUG(("in mouse move\n\r")); if (self == 0) return 0; if (x < 0) @@ -854,6 +640,8 @@ int xrdp_wm_mouse_move(struct xrdp_wm* self, int x, int y) x = self->screen->width; if (y >= self->screen->height) y = self->screen->height; + self->mouse_x = x; + self->mouse_y = y; if (self->dragging) { xrdp_painter_begin_update(self->painter); @@ -868,8 +656,17 @@ int xrdp_wm_mouse_move(struct xrdp_wm* self, int x, int y) xrdp_wm_xor_pat(self, boxx, boxy, self->draggingcx, self->draggingcy); self->draggingxorstate = 1; xrdp_painter_end_update(self->painter); + return 0; } b = xrdp_wm_at_pos(self->screen, x, y, 0); + if (b == 0) + { + if (self->mod != 0) /* if screen is mod controled */ + { + if (self->mod->mod_event != 0) + self->mod->mod_event((int)self->mod, WM_MOUSEMOVE, x, y); + } + } if (self->button_down != 0) { if (b == self->button_down && self->button_down->state == 0) @@ -900,7 +697,6 @@ int xrdp_wm_mouse_move(struct xrdp_wm* self, int x, int y) b->notify(b->owner, b, 2, x, y); } } - DEBUG(("out mouse move\n\r")); return 0; } @@ -966,6 +762,41 @@ int xrdp_wm_mouse_click(struct xrdp_wm* self, int x, int y, int but, int down) } wnd = 0; control = xrdp_wm_at_pos(self->screen, x, y, &wnd); + if (control == 0) + { + if (self->mod != 0) /* if screen is mod controled */ + { + if (self->mod->mod_event != 0) + { + if (but == 1 && down) + self->mod->mod_event((int)self->mod, WM_LBUTTONDOWN, x, y); + else if (but == 1 && !down) + self->mod->mod_event((int)self->mod, WM_LBUTTONUP, x, y); + if (but == 2 && down) + self->mod->mod_event((int)self->mod, WM_RBUTTONDOWN, x, y); + else if (but == 2 && !down) + self->mod->mod_event((int)self->mod, WM_RBUTTONUP, x, y); + if (but == 3 && down) + self->mod->mod_event((int)self->mod, WM_BUTTON3DOWN, x, y); + else if (but == 3 && !down) + self->mod->mod_event((int)self->mod, WM_BUTTON3UP, x, y); + if (but == 4) + { + self->mod->mod_event((int)self->mod, WM_BUTTON4DOWN, + self->mouse_x, self->mouse_y); + self->mod->mod_event((int)self->mod, WM_BUTTON4UP, + self->mouse_x, self->mouse_y); + } + if (but == 5) + { + self->mod->mod_event((int)self->mod, WM_BUTTON5DOWN, + self->mouse_x, self->mouse_y); + self->mod->mod_event((int)self->mod, WM_BUTTON5UP, + self->mouse_x, self->mouse_y); + } + } + } + } if (self->popup_wnd != 0) { if (self->popup_wnd == control && !down) @@ -1056,6 +887,7 @@ int xrdp_wm_mouse_click(struct xrdp_wm* self, int x, int y, int but, int down) /* no matter what, mouse is up, reset button_down */ if (but == 1 && !down && self->button_down != 0) self->button_down = 0; + return 0; } @@ -1063,7 +895,9 @@ int xrdp_wm_mouse_click(struct xrdp_wm* self, int x, int y, int but, int down) int xrdp_wm_key(struct xrdp_wm* self, int device_flags, int scan_code) { int msg; + char c; + scan_code = scan_code % 128; if (self->popup_wnd != 0) { xrdp_wm_clear_popup(self); @@ -1071,12 +905,12 @@ int xrdp_wm_key(struct xrdp_wm* self, int device_flags, int scan_code) } if (device_flags & 0x8000) /* key up */ { - self->keys[scan_code % 128] = 0; + self->keys[scan_code] = 0; msg = WM_KEYUP; } else /* key down */ { - self->keys[scan_code % 128] = 1; + self->keys[scan_code] = 1; msg = WM_KEYDOWN; switch (scan_code) { @@ -1085,7 +919,21 @@ int xrdp_wm_key(struct xrdp_wm* self, int device_flags, int scan_code) case 70: self->scroll_lock = !self->scroll_lock; break; /* scroll lock */ } } - if (self->focused_window != 0) + if (self->mod != 0) + { + if (self->mod->mod_event != 0) + { + c = get_char_from_scan_code(device_flags, scan_code, self->keys, + self->caps_lock, + self->num_lock, + self->scroll_lock); + if (c != 0) + self->mod->mod_event((int)self->mod, msg, c, 0xffff); + else + self->mod->mod_event((int)self->mod, msg, scan_code, device_flags); + } + } + else if (self->focused_window != 0) { xrdp_bitmap_def_proc(self->focused_window, msg, scan_code, device_flags);