summaryrefslogtreecommitdiff
path: root/noncore/net/opierdesktop
authormickeyl <mickeyl>2003-08-10 15:17:24 (UTC)
committer mickeyl <mickeyl>2003-08-10 15:17:24 (UTC)
commit1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f (patch) (unidiff)
tree73b54db5d3aa3e40f4159079c14c8fca90a76c1e /noncore/net/opierdesktop
parentdf6337abb65463b466435a526bf62108e72a60f7 (diff)
downloadopie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.zip
opie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.tar.gz
opie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.tar.bz2
initial import of qtrdesktop - not yet opiefied but working
Diffstat (limited to 'noncore/net/opierdesktop') (more/less context) (show whitespace changes)
-rw-r--r--noncore/net/opierdesktop/.cvsignore4
-rw-r--r--noncore/net/opierdesktop/bitmap.cpp282
-rw-r--r--noncore/net/opierdesktop/cache.cpp235
-rw-r--r--noncore/net/opierdesktop/constants.h259
-rw-r--r--noncore/net/opierdesktop/iso.cpp170
-rw-r--r--noncore/net/opierdesktop/licence.cpp314
-rw-r--r--noncore/net/opierdesktop/mcs.cpp394
-rw-r--r--noncore/net/opierdesktop/opie-rdesktop.control9
-rw-r--r--noncore/net/opierdesktop/opierdesktop.pro26
-rw-r--r--noncore/net/opierdesktop/orders.cpp940
-rw-r--r--noncore/net/opierdesktop/orders.h286
-rw-r--r--noncore/net/opierdesktop/parse.h108
-rw-r--r--noncore/net/opierdesktop/proto.h121
-rw-r--r--noncore/net/opierdesktop/qtwin.cpp1725
-rw-r--r--noncore/net/opierdesktop/qtwin.h105
-rw-r--r--noncore/net/opierdesktop/rdesktop.cpp313
-rw-r--r--noncore/net/opierdesktop/rdesktop.h66
-rw-r--r--noncore/net/opierdesktop/rdp.cpp748
-rw-r--r--noncore/net/opierdesktop/secure.cpp658
-rw-r--r--noncore/net/opierdesktop/tcp.cpp181
-rw-r--r--noncore/net/opierdesktop/types.h110
21 files changed, 7054 insertions, 0 deletions
diff --git a/noncore/net/opierdesktop/.cvsignore b/noncore/net/opierdesktop/.cvsignore
new file mode 100644
index 0000000..df6ec24
--- a/dev/null
+++ b/noncore/net/opierdesktop/.cvsignore
@@ -0,0 +1,4 @@
1*.o
2*~
3Makefile*
4moc_*
diff --git a/noncore/net/opierdesktop/bitmap.cpp b/noncore/net/opierdesktop/bitmap.cpp
new file mode 100644
index 0000000..378623f
--- a/dev/null
+++ b/noncore/net/opierdesktop/bitmap.cpp
@@ -0,0 +1,282 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Bitmap decompression routines
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "rdesktop.h"
22
23#define CVAL(p) (*(p++))
24
25static uint32
26cvalx(unsigned char **input, int Bpp)
27{
28 uint32 rv = 0;
29 memcpy(&rv, *input, Bpp);
30 *input += Bpp;
31 return rv;
32}
33
34static void
35setli(unsigned char *input, int offset, uint32 value, int Bpp)
36{
37 input += offset * Bpp;
38 memcpy(input, &value, Bpp);
39}
40
41static uint32
42getli(unsigned char *input, int offset, int Bpp)
43{
44 uint32 rv = 0;
45 input += offset * Bpp;
46 memcpy(&rv, input, Bpp);
47 return rv;
48}
49
50#define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
51
52#define REPEAT(statement) \
53{ \
54 while((count & ~0x7) && ((x+8) < width)) \
55 UNROLL8( statement; count--; x++; ); \
56 \
57 while((count > 0) && (x < width)) { statement; count--; x++; } \
58}
59
60#define MASK_UPDATE() \
61{ \
62 mixmask <<= 1; \
63 if (mixmask == 0) \
64 { \
65 mask = fom_mask ? fom_mask : CVAL(input); \
66 mixmask = 1; \
67 } \
68}
69
70BOOL
71bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size,
72 int Bpp)
73{
74 unsigned char *end = input + size;
75 unsigned char *prevline = NULL, *line = NULL;
76 int opcode, count, offset, isfillormix, x = width;
77 int lastopcode = -1, insertmix = False, bicolour = False;
78 uint8 code;
79 uint32 colour1 = 0, colour2 = 0;
80 uint8 mixmask, mask = 0;
81 uint32 mix = 0xffffffff;
82 int fom_mask = 0;
83
84 while (input < end)
85 {
86 fom_mask = 0;
87 code = CVAL(input);
88 opcode = code >> 4;
89
90 /* Handle different opcode forms */
91 switch (opcode)
92 {
93 case 0xc:
94 case 0xd:
95 case 0xe:
96 opcode -= 6;
97 count = code & 0xf;
98 offset = 16;
99 break;
100
101 case 0xf:
102 opcode = code & 0xf;
103 if (opcode < 9)
104 {
105 count = CVAL(input);
106 count |= CVAL(input) << 8;
107 }
108 else
109 {
110 count = (opcode < 0xb) ? 8 : 1;
111 }
112 offset = 0;
113 break;
114
115 default:
116 opcode >>= 1;
117 count = code & 0x1f;
118 offset = 32;
119 break;
120 }
121
122 /* Handle strange cases for counts */
123 if (offset != 0)
124 {
125 isfillormix = ((opcode == 2) || (opcode == 7));
126
127 if (count == 0)
128 {
129 if (isfillormix)
130 count = CVAL(input) + 1;
131 else
132 count = CVAL(input) + offset;
133 }
134 else if (isfillormix)
135 {
136 count <<= 3;
137 }
138 }
139
140 /* Read preliminary data */
141 switch (opcode)
142 {
143 case 0:/* Fill */
144 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
145 insertmix = True;
146 break;
147 case 8:/* Bicolour */
148 colour1 = cvalx(&input, Bpp);
149 case 3:/* Colour */
150 colour2 = cvalx(&input, Bpp);
151 break;
152 case 6:/* SetMix/Mix */
153 case 7:/* SetMix/FillOrMix */
154 mix = cvalx(&input, Bpp);
155 opcode -= 5;
156 break;
157 case 9:/* FillOrMix_1 */
158 mask = 0x03;
159 opcode = 0x02;
160 fom_mask = 3;
161 break;
162 case 0x0a:/* FillOrMix_2 */
163 mask = 0x05;
164 opcode = 0x02;
165 fom_mask = 5;
166 break;
167
168 }
169
170 lastopcode = opcode;
171 mixmask = 0;
172
173 /* Output body */
174 while (count > 0)
175 {
176 if (x >= width)
177 {
178 if (height <= 0)
179 return False;
180
181 x = 0;
182 height--;
183
184 prevline = line;
185 line = output + height * width * Bpp;
186 }
187
188 switch (opcode)
189 {
190 case 0:/* Fill */
191 if (insertmix)
192 {
193 if (prevline == NULL)
194 setli(line, x, mix, Bpp);
195 else
196 setli(line, x,
197 getli(prevline, x, Bpp) ^ mix, Bpp);
198
199 insertmix = False;
200 count--;
201 x++;
202 }
203
204 if (prevline == NULL)
205 {
206 REPEAT(setli(line, x, 0, Bpp))}
207 else
208 {
209 REPEAT(setli
210 (line, x, getli(prevline, x, Bpp), Bpp));
211 }
212 break;
213
214 case 1:/* Mix */
215 if (prevline == NULL)
216 {
217 REPEAT(setli(line, x, mix, Bpp));
218 }
219 else
220 {
221 REPEAT(setli
222 (line, x, getli(prevline, x, Bpp) ^ mix,
223 Bpp));
224 }
225 break;
226
227 case 2:/* Fill or Mix */
228 if (prevline == NULL)
229 {
230 REPEAT(MASK_UPDATE();
231 if (mask & mixmask) setli(line, x, mix, Bpp);
232 else
233 setli(line, x, 0, Bpp););
234 }
235 else
236 {
237 REPEAT(MASK_UPDATE();
238 if (mask & mixmask)
239 setli(line, x, getli(prevline, x, Bpp) ^ mix,
240 Bpp);
241 else
242 setli(line, x, getli(prevline, x, Bpp),
243 Bpp););
244 }
245 break;
246
247 case 3:/* Colour */
248 REPEAT(setli(line, x, colour2, Bpp));
249 break;
250
251 case 4:/* Copy */
252 REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));
253 break;
254
255 case 8:/* Bicolour */
256 REPEAT(if (bicolour)
257 {
258 setli(line, x, colour2, Bpp); bicolour = False;}
259 else
260 {
261 setli(line, x, colour1, Bpp); bicolour = True;
262 count++;}
263 );
264 break;
265
266 case 0xd:/* White */
267 REPEAT(setli(line, x, 0xffffffff, Bpp));
268 break;
269
270 case 0xe:/* Black */
271 REPEAT(setli(line, x, 0, Bpp));
272 break;
273
274 default:
275 unimpl("bitmap opcode 0x%x\n", opcode);
276 return False;
277 }
278 }
279 }
280
281 return True;
282}
diff --git a/noncore/net/opierdesktop/cache.cpp b/noncore/net/opierdesktop/cache.cpp
new file mode 100644
index 0000000..42ab135
--- a/dev/null
+++ b/noncore/net/opierdesktop/cache.cpp
@@ -0,0 +1,235 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Cache routines
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "rdesktop.h"
22
23#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
24
25
26/* BITMAP CACHE */
27static HBITMAP bmpcache[3][600];
28
29/* Retrieve a bitmap from the cache */
30HBITMAP
31cache_get_bitmap(uint8 cache_id, uint16 cache_idx)
32{
33 HBITMAP bitmap;
34
35 if ((cache_id < NUM_ELEMENTS(bmpcache)) && (cache_idx < NUM_ELEMENTS(bmpcache[0])))
36 {
37 bitmap = bmpcache[cache_id][cache_idx];
38 if (bitmap != NULL)
39 return bitmap;
40 }
41
42 error("get bitmap %d:%d\n", cache_id, cache_idx);
43 return NULL;
44}
45
46/* Store a bitmap in the cache */
47void
48cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap)
49{
50 HBITMAP old;
51
52 if ((cache_id < NUM_ELEMENTS(bmpcache)) && (cache_idx < NUM_ELEMENTS(bmpcache[0])))
53 {
54 old = bmpcache[cache_id][cache_idx];
55 if (old != NULL)
56 ui_destroy_bitmap(old);
57
58 bmpcache[cache_id][cache_idx] = bitmap;
59 }
60 else
61 {
62 error("put bitmap %d:%d\n", cache_id, cache_idx);
63 }
64}
65
66
67/* FONT CACHE */
68static FONTGLYPH fontcache[12][256];
69
70/* Retrieve a glyph from the font cache */
71FONTGLYPH *
72cache_get_font(uint8 font, uint16 character)
73{
74 FONTGLYPH *glyph;
75
76 if ((font < NUM_ELEMENTS(fontcache)) && (character < NUM_ELEMENTS(fontcache[0])))
77 {
78 glyph = &fontcache[font][character];
79 if (glyph->pixmap != NULL)
80 return glyph;
81 }
82
83 error("get font %d:%d\n", font, character);
84 return NULL;
85}
86
87/* Store a glyph in the font cache */
88void
89cache_put_font(uint8 font, uint16 character, uint16 offset,
90 uint16 baseline, uint16 width, uint16 height, HGLYPH pixmap)
91{
92 FONTGLYPH *glyph;
93
94 if ((font < NUM_ELEMENTS(fontcache)) && (character < NUM_ELEMENTS(fontcache[0])))
95 {
96 glyph = &fontcache[font][character];
97 if (glyph->pixmap != NULL)
98 ui_destroy_glyph(glyph->pixmap);
99
100 glyph->offset = offset;
101 glyph->baseline = baseline;
102 glyph->width = width;
103 glyph->height = height;
104 glyph->pixmap = pixmap;
105 }
106 else
107 {
108 error("put font %d:%d\n", font, character);
109 }
110}
111
112
113/* TEXT CACHE */
114static DATABLOB textcache[256];
115
116/* Retrieve a text item from the cache */
117DATABLOB *
118cache_get_text(uint8 cache_id)
119{
120 DATABLOB *text;
121
122 if (cache_id < NUM_ELEMENTS(textcache))
123 {
124 text = &textcache[cache_id];
125 if (text->data != NULL)
126 return text;
127 }
128
129 error("get text %d\n", cache_id);
130 return NULL;
131}
132
133/* Store a text item in the cache */
134void
135cache_put_text(uint8 cache_id, void *data, int length)
136{
137 DATABLOB *text;
138
139 if (cache_id < NUM_ELEMENTS(textcache))
140 {
141 text = &textcache[cache_id];
142 if (text->data != NULL)
143 xfree(text->data);
144
145 text->data = xmalloc(length);
146 text->size = length;
147 memcpy(text->data, data, length);
148 }
149 else
150 {
151 error("put text %d\n", cache_id);
152 }
153}
154
155
156/* DESKTOP CACHE */
157static uint8 deskcache[0x38400];
158
159/* Retrieve desktop data from the cache */
160uint8 *
161cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel)
162{
163 int length = cx * cy * bytes_per_pixel;
164
165 if ((offset + length) <= sizeof(deskcache))
166 {
167 return &deskcache[offset];
168 }
169
170 error("get desktop %d:%d\n", offset, length);
171 return NULL;
172}
173
174/* Store desktop data in the cache */
175void
176cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8 * data)
177{
178 int length = cx * cy * bytes_per_pixel;
179
180 if ((offset + length) <= sizeof(deskcache))
181 {
182 cx *= bytes_per_pixel;
183 while (cy--)
184 {
185 memcpy(&deskcache[offset], data, cx);
186 data += scanline;
187 offset += cx;
188 }
189 }
190 else
191 {
192 error("put desktop %d:%d\n", offset, length);
193 }
194}
195
196
197/* CURSOR CACHE */
198static HCURSOR cursorcache[0x20];
199
200/* Retrieve cursor from cache */
201HCURSOR
202cache_get_cursor(uint16 cache_idx)
203{
204 HCURSOR cursor;
205
206 if (cache_idx < NUM_ELEMENTS(cursorcache))
207 {
208 cursor = cursorcache[cache_idx];
209 if (cursor != NULL)
210 return cursor;
211 }
212
213 error("get cursor %d\n", cache_idx);
214 return NULL;
215}
216
217/* Store cursor in cache */
218void
219cache_put_cursor(uint16 cache_idx, HCURSOR cursor)
220{
221 HCURSOR old;
222
223 if (cache_idx < NUM_ELEMENTS(cursorcache))
224 {
225 old = cursorcache[cache_idx];
226 if (old != NULL)
227 ui_destroy_cursor(old);
228
229 cursorcache[cache_idx] = cursor;
230 }
231 else
232 {
233 error("put cursor %d\n", cache_idx);
234 }
235}
diff --git a/noncore/net/opierdesktop/constants.h b/noncore/net/opierdesktop/constants.h
new file mode 100644
index 0000000..6dfbf93
--- a/dev/null
+++ b/noncore/net/opierdesktop/constants.h
@@ -0,0 +1,259 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Miscellaneous protocol constants
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21/* TCP port for Remote Desktop Protocol */
22#define TCP_PORT_RDP 3389
23
24/* ISO PDU codes */
25enum ISO_PDU_CODE
26{
27 ISO_PDU_CR = 0xE0,/* Connection Request */
28 ISO_PDU_CC = 0xD0,/* Connection Confirm */
29 ISO_PDU_DR = 0x80,/* Disconnect Request */
30 ISO_PDU_DT = 0xF0,/* Data */
31 ISO_PDU_ER = 0x70/* Error */
32};
33
34/* MCS PDU codes */
35enum MCS_PDU_TYPE
36{
37 MCS_EDRQ = 1, /* Erect Domain Request */
38 MCS_DPUM = 8, /* Disconnect Provider Ultimatum */
39 MCS_AURQ = 10, /* Attach User Request */
40 MCS_AUCF = 11, /* Attach User Confirm */
41 MCS_CJRQ = 14, /* Channel Join Request */
42 MCS_CJCF = 15, /* Channel Join Confirm */
43 MCS_SDRQ = 25, /* Send Data Request */
44 MCS_SDIN = 26 /* Send Data Indication */
45};
46
47 #define MCS_CONNECT_INITIAL0x7f65
48 #define MCS_CONNECT_RESPONSE0x7f66
49
50 #define BER_TAG_BOOLEAN 1
51 #define BER_TAG_INTEGER 2
52 #define BER_TAG_OCTET_STRING4
53 #define BER_TAG_RESULT 10
54 #define MCS_TAG_DOMAIN_PARAMS0x30
55
56 #define MCS_GLOBAL_CHANNEL1003
57
58/* RDP secure transport constants */
59 #define SEC_RANDOM_SIZE 32
60 #define SEC_MODULUS_SIZE64
61 #define SEC_PADDING_SIZE8
62 #define SEC_EXPONENT_SIZE4
63
64 #define SEC_CLIENT_RANDOM0x0001
65 #define SEC_ENCRYPT 0x0008
66 #define SEC_LOGON_INFO 0x0040
67 #define SEC_LICENCE_NEG 0x0080
68
69 #define SEC_TAG_SRV_INFO0x0c01
70 #define SEC_TAG_SRV_CRYPT0x0c02
71 #define SEC_TAG_SRV_3 0x0c03
72
73 #define SEC_TAG_CLI_INFO0xc001
74 #define SEC_TAG_CLI_CRYPT0xc002
75
76 #define SEC_TAG_PUBKEY 0x0006
77 #define SEC_TAG_KEYSIG 0x0008
78
79 #define SEC_RSA_MAGIC 0x31415352/* RSA1 */
80
81/* RDP licensing constants */
82 #define LICENCE_TOKEN_SIZE10
83 #define LICENCE_HWID_SIZE20
84 #define LICENCE_SIGNATURE_SIZE16
85
86 #define LICENCE_TAG_DEMAND0x0201
87 #define LICENCE_TAG_AUTHREQ0x0202
88 #define LICENCE_TAG_ISSUE0x0203
89 #define LICENCE_TAG_REISSUE0x0204
90 #define LICENCE_TAG_PRESENT0x0212
91 #define LICENCE_TAG_REQUEST0x0213
92 #define LICENCE_TAG_AUTHRESP0x0215
93 #define LICENCE_TAG_RESULT0x02ff
94
95 #define LICENCE_TAG_USER0x000f
96 #define LICENCE_TAG_HOST0x0010
97
98/* RDP PDU codes */
99enum RDP_PDU_TYPE
100{
101 RDP_PDU_DEMAND_ACTIVE = 1,
102 RDP_PDU_CONFIRM_ACTIVE = 3,
103 RDP_PDU_DEACTIVATE = 6,
104 RDP_PDU_DATA = 7
105};
106
107enum RDP_DATA_PDU_TYPE
108{
109 RDP_DATA_PDU_UPDATE = 2,
110 RDP_DATA_PDU_CONTROL = 20,
111 RDP_DATA_PDU_POINTER = 27,
112 RDP_DATA_PDU_INPUT = 28,
113 RDP_DATA_PDU_SYNCHRONISE = 31,
114 RDP_DATA_PDU_BELL = 34,
115 RDP_DATA_PDU_LOGON = 38,
116 RDP_DATA_PDU_FONT2 = 39
117};
118
119enum RDP_CONTROL_PDU_TYPE
120{
121 RDP_CTL_REQUEST_CONTROL = 1,
122 RDP_CTL_GRANT_CONTROL = 2,
123 RDP_CTL_DETACH = 3,
124 RDP_CTL_COOPERATE = 4
125};
126
127enum RDP_UPDATE_PDU_TYPE
128{
129 RDP_UPDATE_ORDERS = 0,
130 RDP_UPDATE_BITMAP = 1,
131 RDP_UPDATE_PALETTE = 2,
132 RDP_UPDATE_SYNCHRONIZE = 3
133};
134
135enum RDP_POINTER_PDU_TYPE
136{
137 RDP_POINTER_MOVE = 3,
138 RDP_POINTER_COLOR = 6,
139 RDP_POINTER_CACHED = 7
140};
141
142enum RDP_INPUT_DEVICE
143{
144 RDP_INPUT_SYNCHRONIZE = 0,
145 RDP_INPUT_CODEPOINT = 1,
146 RDP_INPUT_VIRTKEY = 2,
147 RDP_INPUT_SCANCODE = 4,
148 RDP_INPUT_MOUSE = 0x8001
149};
150
151/* Device flags */
152#define KBD_FLAG_RIGHT 0x0001
153#define KBD_FLAG_EXT 0x0100
154#define KBD_FLAG_QUIET 0x1000
155#define KBD_FLAG_DOWN 0x4000
156#define KBD_FLAG_UP 0x8000
157
158/* These are for synchronization; not for keystrokes */
159#define KBD_FLAG_SCROLL 0x0001
160#define KBD_FLAG_NUMLOCK 0x0002
161#define KBD_FLAG_CAPITAL 0x0004
162
163/* See T.128 */
164#define RDP_KEYPRESS 0
165#define RDP_KEYRELEASE (KBD_FLAG_DOWN | KBD_FLAG_UP)
166
167#define MOUSE_FLAG_MOVE 0x0800
168#define MOUSE_FLAG_BUTTON1 0x1000
169#define MOUSE_FLAG_BUTTON2 0x2000
170#define MOUSE_FLAG_BUTTON3 0x4000
171#define MOUSE_FLAG_BUTTON4 0x0280
172#define MOUSE_FLAG_BUTTON5 0x0380
173#define MOUSE_FLAG_DOWN 0x8000
174
175/* Raster operation masks */
176#define ROP2_S(rop3) (rop3 & 0xf)
177#define ROP2_P(rop3) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2))
178
179 #define ROP2_COPY0xc
180 #define ROP2_XOR0x6
181 #define ROP2_AND0x8
182 #define ROP2_NXOR0x9
183 #define ROP2_OR 0xe
184
185 #define MIX_TRANSPARENT0
186 #define MIX_OPAQUE1
187
188 #define TEXT2_VERTICAL 0x04
189 #define TEXT2_IMPLICIT_X0x20
190
191/* RDP capabilities */
192 #define RDP_CAPSET_GENERAL1
193 #define RDP_CAPLEN_GENERAL0x18
194 #define OS_MAJOR_TYPE_UNIX4
195 #define OS_MINOR_TYPE_XSERVER7
196
197 #define RDP_CAPSET_BITMAP2
198 #define RDP_CAPLEN_BITMAP0x1C
199
200 #define RDP_CAPSET_ORDER3
201 #define RDP_CAPLEN_ORDER0x58
202 #define ORDER_CAP_NEGOTIATE2
203 #define ORDER_CAP_NOSUPPORT4
204
205 #define RDP_CAPSET_BMPCACHE4
206 #define RDP_CAPLEN_BMPCACHE0x28
207
208 #define RDP_CAPSET_CONTROL5
209 #define RDP_CAPLEN_CONTROL0x0C
210
211 #define RDP_CAPSET_ACTIVATE7
212 #define RDP_CAPLEN_ACTIVATE0x0C
213
214 #define RDP_CAPSET_POINTER8
215 #define RDP_CAPLEN_POINTER0x08
216
217 #define RDP_CAPSET_SHARE9
218 #define RDP_CAPLEN_SHARE0x08
219
220 #define RDP_CAPSET_COLCACHE10
221 #define RDP_CAPLEN_COLCACHE0x08
222
223 #define RDP_CAPSET_UNKNOWN13
224 #define RDP_CAPLEN_UNKNOWN0x9C
225
226 #define RDP_SOURCE "MSTSC"
227
228/* Logon flags */
229 #define RDP_LOGON_NORMAL0x33
230 #define RDP_LOGON_AUTO 0x8
231
232/* Keymap flags */
233#define MapRightShiftMask (1<<0)
234#define MapLeftShiftMask (1<<1)
235#define MapShiftMask (MapRightShiftMask | MapLeftShiftMask)
236
237#define MapRightAltMask (1<<2)
238#define MapLeftAltMask (1<<3)
239#define MapAltGrMask MapRightAltMask
240
241#define MapRightCtrlMask (1<<4)
242#define MapLeftCtrlMask (1<<5)
243#define MapCtrlMask (MapRightCtrlMask | MapLeftCtrlMask)
244
245#define MapRightWinMask (1<<6)
246#define MapLeftWinMask (1<<7)
247#define MapWinMask (MapRightWinMask | MapLeftWinMask)
248
249#define MapNumLockMask (1<<8)
250#define MapCapsLockMask (1<<9)
251
252#define MapLocalStateMask (1<<10)
253
254#define MapInhibitMask (1<<11)
255
256#define MASK_ADD_BITS(var, mask) (var |= mask)
257#define MASK_REMOVE_BITS(var, mask) (var &= ~mask)
258#define MASK_HAS_BITS(var, mask) ((var & mask)>0)
259#define MASK_CHANGE_BIT(var, mask, active) (var = ((var & ~mask) | (active ? mask : 0)))
diff --git a/noncore/net/opierdesktop/iso.cpp b/noncore/net/opierdesktop/iso.cpp
new file mode 100644
index 0000000..0fa1a17
--- a/dev/null
+++ b/noncore/net/opierdesktop/iso.cpp
@@ -0,0 +1,170 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - ISO layer
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "rdesktop.h"
22
23/* Send a self-contained ISO PDU */
24static void
25iso_send_msg(uint8 code)
26{
27 STREAM s;
28
29 s = tcp_init(11);
30
31 out_uint8(s, 3);/* version */
32 out_uint8(s, 0);/* reserved */
33 out_uint16_be(s, 11);/* length */
34
35 out_uint8(s, 6);/* hdrlen */
36 out_uint8(s, code);
37 out_uint16(s, 0);/* dst_ref */
38 out_uint16(s, 0);/* src_ref */
39 out_uint8(s, 0);/* class */
40
41 s_mark_end(s);
42 tcp_send(s);
43}
44
45/* Receive a message on the ISO layer, return code */
46static STREAM
47iso_recv_msg(uint8 * code)
48{
49 STREAM s;
50 uint16 length;
51 uint8 version;
52
53 s = tcp_recv(4);
54 if (s == NULL)
55 {
56 return NULL;
57 }
58
59 in_uint8(s, version);
60 if (version != 3)
61 {
62 error("TPKT v%d\n", version);
63 return NULL;
64 }
65
66 in_uint8s(s, 1);/* pad */
67 in_uint16_be(s, length);
68
69 s = tcp_recv(length - 4);
70 if (s == NULL)
71 return NULL;
72
73 in_uint8s(s, 1);/* hdrlen */
74 in_uint8(s, *code);
75
76 if (*code == ISO_PDU_DT)
77 {
78 in_uint8s(s, 1);/* eot */
79 return s;
80 }
81
82 in_uint8s(s, 5);/* dst_ref, src_ref, class */
83 return s;
84}
85
86/* Initialise ISO transport data packet */
87STREAM
88iso_init(int length)
89{
90 STREAM s;
91
92 s = tcp_init(length + 7);
93 s_push_layer(s, iso_hdr, 7);
94
95 return s;
96}
97
98/* Send an ISO data PDU */
99void
100iso_send(STREAM s)
101{
102 uint16 length;
103
104 s_pop_layer(s, iso_hdr);
105 length = s->end - s->p;
106
107 out_uint8(s, 3);/* version */
108 out_uint8(s, 0);/* reserved */
109 out_uint16_be(s, length);
110
111 out_uint8(s, 2);/* hdrlen */
112 out_uint8(s, ISO_PDU_DT);/* code */
113 out_uint8(s, 0x80);/* eot */
114
115 tcp_send(s);
116}
117
118/* Receive ISO transport data packet */
119STREAM
120iso_recv(void)
121{
122 STREAM s;
123 uint8 code;
124
125 s = iso_recv_msg(&code);
126 if (s == NULL)
127 return NULL;
128
129 if (code != ISO_PDU_DT)
130 {
131 error("expected DT, got 0x%x\n", code);
132 return NULL;
133 }
134
135 return s;
136}
137
138/* Establish a connection up to the ISO layer */
139BOOL
140iso_connect(char *server)
141{
142 uint8 code;
143
144 if (!tcp_connect(server))
145 return False;
146
147 iso_send_msg(ISO_PDU_CR);
148
149 if (iso_recv_msg(&code) == NULL)
150 {
151 return False;
152 }
153
154 if (code != ISO_PDU_CC)
155 {
156 error("expected CC, got 0x%x\n", code);
157 tcp_disconnect();
158 return False;
159 }
160
161 return True;
162}
163
164/* Disconnect from the ISO layer */
165void
166iso_disconnect(void)
167{
168 iso_send_msg(ISO_PDU_DR);
169 tcp_disconnect();
170}
diff --git a/noncore/net/opierdesktop/licence.cpp b/noncore/net/opierdesktop/licence.cpp
new file mode 100644
index 0000000..4e5bc38
--- a/dev/null
+++ b/noncore/net/opierdesktop/licence.cpp
@@ -0,0 +1,314 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 RDP licensing negotiation
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "rdesktop.h"
22
23#ifdef WITH_OPENSSL
24#include <openssl/rc4.h>
25#else
26#include "crypto/rc4.h"
27#endif
28
29extern char username[16];
30extern char hostname[16];
31
32static uint8 licence_key[16];
33static uint8 licence_sign_key[16];
34
35BOOL licence_issued = False;
36
37/* Generate a session key and RC4 keys, given client and server randoms */
38static void
39licence_generate_keys(uint8 * client_key, uint8 * server_key, uint8 * client_rsa)
40{
41 uint8 session_key[48];
42 uint8 temp_hash[48];
43
44 /* Generate session key - two rounds of sec_hash_48 */
45 sec_hash_48(temp_hash, client_rsa, client_key, server_key, 65);
46 sec_hash_48(session_key, temp_hash, server_key, client_key, 65);
47
48 /* Store first 16 bytes of session key, for generating signatures */
49 memcpy(licence_sign_key, session_key, 16);
50
51 /* Generate RC4 key */
52 sec_hash_16(licence_key, &session_key[16], client_key, server_key);
53}
54
55static void
56licence_generate_hwid(uint8 * hwid)
57{
58 buf_out_uint32(hwid, 2);
59 strncpy((char *) (hwid + 4), hostname, LICENCE_HWID_SIZE - 4);
60}
61
62/* Present an existing licence to the server */
63static void
64licence_present(uint8 * client_random, uint8 * rsa_data,
65 uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
66{
67 uint32 sec_flags = SEC_LICENCE_NEG;
68 uint16 length =
69 16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
70 licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
71 STREAM s;
72
73 s = sec_init(sec_flags, length + 4);
74
75 out_uint16_le(s, LICENCE_TAG_PRESENT);
76 out_uint16_le(s, length);
77
78 out_uint32_le(s, 1);
79 out_uint16(s, 0);
80 out_uint16_le(s, 0x0201);
81
82 out_uint8p(s, client_random, SEC_RANDOM_SIZE);
83 out_uint16(s, 0);
84 out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
85 out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
86 out_uint8s(s, SEC_PADDING_SIZE);
87
88 out_uint16_le(s, 1);
89 out_uint16_le(s, licence_size);
90 out_uint8p(s, licence_data, licence_size);
91
92 out_uint16_le(s, 1);
93 out_uint16_le(s, LICENCE_HWID_SIZE);
94 out_uint8p(s, hwid, LICENCE_HWID_SIZE);
95
96 out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
97
98 s_mark_end(s);
99 sec_send(s, sec_flags);
100}
101
102/* Send a licence request packet */
103static void
104licence_send_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
105{
106 uint32 sec_flags = SEC_LICENCE_NEG;
107 uint16 userlen = strlen(user) + 1;
108 uint16 hostlen = strlen(host) + 1;
109 uint16 length = 128 + userlen + hostlen;
110 STREAM s;
111
112 s = sec_init(sec_flags, length + 2);
113
114 out_uint16_le(s, LICENCE_TAG_REQUEST);
115 out_uint16_le(s, length);
116
117 out_uint32_le(s, 1);
118 out_uint16(s, 0);
119 out_uint16_le(s, 0xff01);
120
121 out_uint8p(s, client_random, SEC_RANDOM_SIZE);
122 out_uint16(s, 0);
123 out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
124 out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
125 out_uint8s(s, SEC_PADDING_SIZE);
126
127 out_uint16(s, LICENCE_TAG_USER);
128 out_uint16(s, userlen);
129 out_uint8p(s, user, userlen);
130
131 out_uint16(s, LICENCE_TAG_HOST);
132 out_uint16(s, hostlen);
133 out_uint8p(s, host, hostlen);
134
135 s_mark_end(s);
136 sec_send(s, sec_flags);
137}
138
139/* Process a licence demand packet */
140static void
141licence_process_demand(STREAM s)
142{
143 uint8 null_data[SEC_MODULUS_SIZE];
144 uint8 *server_random;
145 uint8 signature[LICENCE_SIGNATURE_SIZE];
146 uint8 hwid[LICENCE_HWID_SIZE];
147 uint8 *licence_data;
148 int licence_size;
149 RC4_KEY crypt_key;
150
151 /* Retrieve the server random from the incoming packet */
152 in_uint8p(s, server_random, SEC_RANDOM_SIZE);
153
154 /* We currently use null client keys. This is a bit naughty but, hey,
155 the security of licence negotiation isn't exactly paramount. */
156 memset(null_data, 0, sizeof(null_data));
157 licence_generate_keys(null_data, server_random, null_data);
158
159 licence_size = load_licence(&licence_data);
160 if (licence_size != -1)
161 {
162 /* Generate a signature for the HWID buffer */
163 licence_generate_hwid(hwid);
164 sec_sign(signature, 16, licence_sign_key, 16, hwid, sizeof(hwid));
165
166 /* Now encrypt the HWID */
167 RC4_set_key(&crypt_key, 16, licence_key);
168 RC4(&crypt_key, sizeof(hwid), hwid, hwid);
169
170 licence_present(null_data, null_data, licence_data, licence_size, hwid, signature);
171 xfree(licence_data);
172 return;
173 }
174
175 licence_send_request(null_data, null_data, username, hostname);
176}
177
178/* Send an authentication response packet */
179static void
180licence_send_authresp(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
181{
182 uint32 sec_flags = SEC_LICENCE_NEG;
183 uint16 length = 58;
184 STREAM s;
185
186 s = sec_init(sec_flags, length + 2);
187
188 out_uint16_le(s, LICENCE_TAG_AUTHRESP);
189 out_uint16_le(s, length);
190
191 out_uint16_le(s, 1);
192 out_uint16_le(s, LICENCE_TOKEN_SIZE);
193 out_uint8p(s, token, LICENCE_TOKEN_SIZE);
194
195 out_uint16_le(s, 1);
196 out_uint16_le(s, LICENCE_HWID_SIZE);
197 out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE);
198
199 out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
200
201 s_mark_end(s);
202 sec_send(s, sec_flags);
203}
204
205/* Parse an authentication request packet */
206static BOOL
207licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature)
208{
209 uint16 tokenlen;
210
211 in_uint8s(s, 6);/* unknown: f8 3d 15 00 04 f6 */
212
213 in_uint16_le(s, tokenlen);
214 if (tokenlen != LICENCE_TOKEN_SIZE)
215 {
216 error("token len %d\n", tokenlen);
217 return False;
218 }
219
220 in_uint8p(s, *token, tokenlen);
221 in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE);
222
223 return s_check_end(s);
224}
225
226/* Process an authentication request packet */
227static void
228licence_process_authreq(STREAM s)
229{
230 uint8 *in_token, *in_sig;
231 uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
232 uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];
233 uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];
234 uint8 out_sig[LICENCE_SIGNATURE_SIZE];
235 RC4_KEY crypt_key;
236
237 /* Parse incoming packet and save the encrypted token */
238 licence_parse_authreq(s, &in_token, &in_sig);
239 memcpy(out_token, in_token, LICENCE_TOKEN_SIZE);
240
241 /* Decrypt the token. It should read TEST in Unicode. */
242 RC4_set_key(&crypt_key, 16, licence_key);
243 RC4(&crypt_key, LICENCE_TOKEN_SIZE, in_token, decrypt_token);
244
245 /* Generate a signature for a buffer of token and HWID */
246 licence_generate_hwid(hwid);
247 memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);
248 memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);
249 sec_sign(out_sig, 16, licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer));
250
251 /* Now encrypt the HWID */
252 RC4_set_key(&crypt_key, 16, licence_key);
253 RC4(&crypt_key, LICENCE_HWID_SIZE, hwid, crypt_hwid);
254
255 licence_send_authresp(out_token, crypt_hwid, out_sig);
256}
257
258/* Process an licence issue packet */
259static void
260licence_process_issue(STREAM s)
261{
262 RC4_KEY crypt_key;
263 uint32 length;
264 uint16 check;
265
266 in_uint8s(s, 2);/* 3d 45 - unknown */
267 in_uint16_le(s, length);
268 if (!s_check_rem(s, length))
269 return;
270
271 RC4_set_key(&crypt_key, 16, licence_key);
272 RC4(&crypt_key, length, s->p, s->p);
273
274 in_uint16(s, check);
275 if (check != 0)
276 return;
277
278 licence_issued = True;
279 save_licence(s->p, length - 2);
280}
281
282/* Process a licence packet */
283void
284licence_process(STREAM s)
285{
286 uint16 tag;
287
288 in_uint16_le(s, tag);
289 in_uint8s(s, 2);/* length */
290
291 switch (tag)
292 {
293 case LICENCE_TAG_DEMAND:
294 licence_process_demand(s);
295 break;
296
297 case LICENCE_TAG_AUTHREQ:
298 licence_process_authreq(s);
299 break;
300
301 case LICENCE_TAG_ISSUE:
302 licence_process_issue(s);
303 break;
304
305 case LICENCE_TAG_REISSUE:
306 break;
307
308 case LICENCE_TAG_RESULT:
309 break;
310
311 default:
312 unimpl("licence tag 0x%x\n", tag);
313 }
314}
diff --git a/noncore/net/opierdesktop/mcs.cpp b/noncore/net/opierdesktop/mcs.cpp
new file mode 100644
index 0000000..8877d62
--- a/dev/null
+++ b/noncore/net/opierdesktop/mcs.cpp
@@ -0,0 +1,394 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - Multipoint Communications Service
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "rdesktop.h"
22
23uint16 mcs_userid;
24
25/* Parse an ASN.1 BER header */
26static BOOL
27ber_parse_header(STREAM s, int tagval, unsigned int *length)
28{
29 int tag, len;
30
31 if (tagval > 0xff)
32 {
33 in_uint16_be(s, tag);
34 }
35 else
36 {
37 in_uint8(s, tag)}
38
39 if (tag != tagval)
40 {
41 error("expected tag %d, got %d\n", tagval, tag);
42 return False;
43 }
44
45 in_uint8(s, len);
46
47 if (len & 0x80)
48 {
49 len &= ~0x80;
50 *length = 0;
51 while (len--)
52 next_be(s, *length);
53 }
54 else
55 *length = len;
56
57 return s_check(s);
58}
59
60/* Output an ASN.1 BER header */
61static void
62ber_out_header(STREAM s, int tagval, int length)
63{
64 if (tagval > 0xff)
65 {
66 out_uint16_be(s, tagval);
67 }
68 else
69 {
70 out_uint8(s, tagval);
71 }
72
73 if (length >= 0x80)
74 {
75 out_uint8(s, 0x82);
76 out_uint16_be(s, length);
77 }
78 else
79 out_uint8(s, length);
80}
81
82/* Output an ASN.1 BER integer */
83static void
84ber_out_integer(STREAM s, int value)
85{
86 ber_out_header(s, BER_TAG_INTEGER, 2);
87 out_uint16_be(s, value);
88}
89
90/* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
91static void
92mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
93{
94 ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);
95 ber_out_integer(s, max_channels);
96 ber_out_integer(s, max_users);
97 ber_out_integer(s, max_tokens);
98 ber_out_integer(s, 1);/* num_priorities */
99 ber_out_integer(s, 0);/* min_throughput */
100 ber_out_integer(s, 1);/* max_height */
101 ber_out_integer(s, max_pdusize);
102 ber_out_integer(s, 2);/* ver_protocol */
103}
104
105/* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
106static BOOL
107mcs_parse_domain_params(STREAM s)
108{
109 unsigned int length;
110
111 ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
112 in_uint8s(s, length);
113
114 return s_check(s);
115}
116
117/* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
118static void
119mcs_send_connect_initial(STREAM mcs_data)
120{
121 int datalen = mcs_data->end - mcs_data->data;
122 int length = 7 + 3 * 34 + 4 + datalen;
123 STREAM s;
124
125 s = iso_init(length + 5);
126
127 ber_out_header(s, MCS_CONNECT_INITIAL, length);
128 ber_out_header(s, BER_TAG_OCTET_STRING, 0);/* calling domain */
129 ber_out_header(s, BER_TAG_OCTET_STRING, 0);/* called domain */
130
131 ber_out_header(s, BER_TAG_BOOLEAN, 1);
132 out_uint8(s, 0xff);/* upward flag */
133
134 mcs_out_domain_params(s, 2, 2, 0, 0xffff);/* target params */
135 mcs_out_domain_params(s, 1, 1, 1, 0x420);/* min params */
136 mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff);/* max params */
137
138 ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
139 out_uint8p(s, mcs_data->data, datalen);
140
141 s_mark_end(s);
142 iso_send(s);
143}
144
145/* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
146static BOOL
147mcs_recv_connect_response(STREAM mcs_data)
148{
149 uint8 result;
150 unsigned int length;
151 STREAM s;
152
153 s = iso_recv();
154 if (s == NULL)
155 return False;
156
157 ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
158
159 ber_parse_header(s, BER_TAG_RESULT, &length);
160 in_uint8(s, result);
161 if (result != 0)
162 {
163 error("MCS connect: %d\n", result);
164 return False;
165 }
166
167 ber_parse_header(s, BER_TAG_INTEGER, &length);
168 in_uint8s(s, length);/* connect id */
169 mcs_parse_domain_params(s);
170
171 ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
172 if (length > mcs_data->size)
173 {
174 error("MCS data length %d\n", length);
175 length = mcs_data->size;
176 }
177
178 in_uint8a(s, mcs_data->data, length);
179 mcs_data->p = mcs_data->data;
180 mcs_data->end = mcs_data->data + length;
181
182 return s_check_end(s);
183}
184
185/* Send an EDrq message (ASN.1 PER) */
186static void
187mcs_send_edrq(void)
188{
189 STREAM s;
190
191 s = iso_init(5);
192
193 out_uint8(s, (MCS_EDRQ << 2));
194 out_uint16_be(s, 1);/* height */
195 out_uint16_be(s, 1);/* interval */
196
197 s_mark_end(s);
198 iso_send(s);
199}
200
201/* Send an AUrq message (ASN.1 PER) */
202static void
203mcs_send_aurq(void)
204{
205 STREAM s;
206
207 s = iso_init(1);
208
209 out_uint8(s, (MCS_AURQ << 2));
210
211 s_mark_end(s);
212 iso_send(s);
213}
214
215/* Expect a AUcf message (ASN.1 PER) */
216static BOOL
217mcs_recv_aucf(uint16 * mcs_userid)
218{
219 uint8 opcode, result;
220 STREAM s;
221
222 s = iso_recv();
223 if (s == NULL)
224 return False;
225
226 in_uint8(s, opcode);
227 if ((opcode >> 2) != MCS_AUCF)
228 {
229 error("expected AUcf, got %d\n", opcode);
230 return False;
231 }
232
233 in_uint8(s, result);
234 if (result != 0)
235 {
236 error("AUrq: %d\n", result);
237 return False;
238 }
239
240 if (opcode & 2)
241 in_uint16_be(s, *mcs_userid);
242
243 return s_check_end(s);
244}
245
246/* Send a CJrq message (ASN.1 PER) */
247static void
248mcs_send_cjrq(uint16 chanid)
249{
250 STREAM s;
251
252 s = iso_init(5);
253
254 out_uint8(s, (MCS_CJRQ << 2));
255 out_uint16_be(s, mcs_userid);
256 out_uint16_be(s, chanid);
257
258 s_mark_end(s);
259 iso_send(s);
260}
261
262/* Expect a CJcf message (ASN.1 PER) */
263static BOOL
264mcs_recv_cjcf(void)
265{
266 uint8 opcode, result;
267 STREAM s;
268
269 s = iso_recv();
270 if (s == NULL)
271 return False;
272
273 in_uint8(s, opcode);
274 if ((opcode >> 2) != MCS_CJCF)
275 {
276 error("expected CJcf, got %d\n", opcode);
277 return False;
278 }
279
280 in_uint8(s, result);
281 if (result != 0)
282 {
283 error("CJrq: %d\n", result);
284 return False;
285 }
286
287 in_uint8s(s, 4);/* mcs_userid, req_chanid */
288 if (opcode & 2)
289 in_uint8s(s, 2);/* join_chanid */
290
291 return s_check_end(s);
292}
293
294/* Initialise an MCS transport data packet */
295STREAM
296mcs_init(int length)
297{
298 STREAM s;
299
300 s = iso_init(length + 8);
301 s_push_layer(s, mcs_hdr, 8);
302
303 return s;
304}
305
306/* Send an MCS transport data packet */
307void
308mcs_send(STREAM s)
309{
310 uint16 length;
311
312 s_pop_layer(s, mcs_hdr);
313 length = s->end - s->p - 8;
314 length |= 0x8000;
315
316 out_uint8(s, (MCS_SDRQ << 2));
317 out_uint16_be(s, mcs_userid);
318 out_uint16_be(s, MCS_GLOBAL_CHANNEL);
319 out_uint8(s, 0x70);/* flags */
320 out_uint16_be(s, length);
321
322 iso_send(s);
323}
324
325/* Receive an MCS transport data packet */
326STREAM
327mcs_recv(void)
328{
329 uint8 opcode, appid, length;
330 STREAM s;
331
332 s = iso_recv();
333 if (s == NULL)
334 return NULL;
335
336 in_uint8(s, opcode);
337 appid = opcode >> 2;
338 if (appid != MCS_SDIN)
339 {
340 if (appid != MCS_DPUM)
341 {
342 error("expected data, got %d\n", opcode);
343 }
344 return NULL;
345 }
346
347 in_uint8s(s, 5);/* userid, chanid, flags */
348 in_uint8(s, length);
349 if (length & 0x80)
350 in_uint8s(s, 1);/* second byte of length */
351
352 return s;
353}
354
355/* Establish a connection up to the MCS layer */
356BOOL
357mcs_connect(char *server, STREAM mcs_data)
358{
359 if (!iso_connect(server))
360 {
361 return False;
362 }
363
364 mcs_send_connect_initial(mcs_data);
365 if (!mcs_recv_connect_response(mcs_data))
366 goto error;
367
368 mcs_send_edrq();
369
370 mcs_send_aurq();
371 if (!mcs_recv_aucf(&mcs_userid))
372 goto error;
373
374 mcs_send_cjrq(mcs_userid + 1001);
375 if (!mcs_recv_cjcf())
376 goto error;
377
378 mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
379 if (!mcs_recv_cjcf())
380 goto error;
381
382 return True;
383
384 error:
385 iso_disconnect();
386 return False;
387}
388
389/* Disconnect from the MCS layer */
390void
391mcs_disconnect(void)
392{
393 iso_disconnect();
394}
diff --git a/noncore/net/opierdesktop/opie-rdesktop.control b/noncore/net/opierdesktop/opie-rdesktop.control
new file mode 100644
index 0000000..3fe3705
--- a/dev/null
+++ b/noncore/net/opierdesktop/opie-rdesktop.control
@@ -0,0 +1,9 @@
1Package: opie-rdesktop
2Files: bin/ordesktop pics/opierdesktop apps/Applications/opierdesktop.desktop
3Priority: optional
4Section: opie/applications
5Maintainer: Michael 'Mickey' Lauer <mickeyl@handhelds.org>
6Architecture: arm
7Version: 1.2.0-$SUB_VERSION
8Depends: task-opie-minimal
9Description: Remote Desktop Protocol (RDP) Client
diff --git a/noncore/net/opierdesktop/opierdesktop.pro b/noncore/net/opierdesktop/opierdesktop.pro
new file mode 100644
index 0000000..7704855
--- a/dev/null
+++ b/noncore/net/opierdesktop/opierdesktop.pro
@@ -0,0 +1,26 @@
1TEMPLATE = app
2DESTDIR = $(OPIEDIR)/bin
3CONFIG = qt warn_on debug
4
5HEADERS += constants.h orders.h parse.h proto.h qtwin.h rdesktop.h types.h
6SOURCES += bitmap.cpp \
7 cache.cpp \
8 iso.cpp \
9 licence.cpp \
10 mcs.cpp \
11 orders.cpp \
12 qtwin.cpp \
13 rdesktop.cpp \
14 rdp.cpp \
15 secure.cpp \
16 tcp.cpp
17
18INCLUDEPATH += $(OPIEDIR)/include
19DEPENDPATH += $(OPIEDIR)/include
20LIBS += -lqpe -lm -lcrypto
21INTERFACES =
22TARGET = ordesktop
23QMAKE_CXXFLAGS += -DSHARP=1 -DWITH_OPENSSL=1
24
25include ( $(OPIEDIR)/include.pro )
26
diff --git a/noncore/net/opierdesktop/orders.cpp b/noncore/net/opierdesktop/orders.cpp
new file mode 100644
index 0000000..194b043
--- a/dev/null
+++ b/noncore/net/opierdesktop/orders.cpp
@@ -0,0 +1,940 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 RDP order processing
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "rdesktop.h"
22#include "orders.h"
23
24extern uint8 *next_packet;
25static RDP_ORDER_STATE order_state;
26
27/* Read field indicating which parameters are present */
28static void
29rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size)
30{
31 uint8 bits;
32 int i;
33
34 if (flags & RDP_ORDER_SMALL)
35 {
36 size--;
37 }
38
39 if (flags & RDP_ORDER_TINY)
40 {
41 if (size < 2)
42 size = 0;
43 else
44 size -= 2;
45 }
46
47 *present = 0;
48 for (i = 0; i < size; i++)
49 {
50 in_uint8(s, bits);
51 *present |= bits << (i * 8);
52 }
53}
54
55/* Read a co-ordinate (16-bit, or 8-bit delta) */
56static void
57rdp_in_coord(STREAM s, sint16 * coord, BOOL delta)
58{
59 sint8 change;
60
61 if (delta)
62 {
63 in_uint8(s, change);
64 *coord += change;
65 }
66 else
67 {
68 in_uint16_le(s, *coord);
69 }
70}
71
72/* Read a colour entry */
73static void
74rdp_in_colour(STREAM s, uint32 * colour)
75{
76 uint32 i;
77 in_uint8(s, i);
78 *colour = i;
79 in_uint8(s, i);
80 *colour |= i << 8;
81 in_uint8(s, i);
82 *colour |= i << 16;
83}
84
85/* Parse bounds information */
86static BOOL
87rdp_parse_bounds(STREAM s, BOUNDS * bounds)
88{
89 uint8 present;
90
91 in_uint8(s, present);
92
93 if (present & 1)
94 rdp_in_coord(s, &bounds->left, False);
95 else if (present & 16)
96 rdp_in_coord(s, &bounds->left, True);
97
98 if (present & 2)
99 rdp_in_coord(s, &bounds->top, False);
100 else if (present & 32)
101 rdp_in_coord(s, &bounds->top, True);
102
103 if (present & 4)
104 rdp_in_coord(s, &bounds->right, False);
105 else if (present & 64)
106 rdp_in_coord(s, &bounds->right, True);
107
108 if (present & 8)
109 rdp_in_coord(s, &bounds->bottom, False);
110 else if (present & 128)
111 rdp_in_coord(s, &bounds->bottom, True);
112
113 return s_check(s);
114}
115
116/* Parse a pen */
117static BOOL
118rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
119{
120 if (present & 1)
121 in_uint8(s, pen->style);
122
123 if (present & 2)
124 in_uint8(s, pen->width);
125
126 if (present & 4)
127 rdp_in_colour(s, &pen->colour);
128
129 return s_check(s);
130}
131
132/* Parse a brush */
133static BOOL
134rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
135{
136 if (present & 1)
137 in_uint8(s, brush->xorigin);
138
139 if (present & 2)
140 in_uint8(s, brush->yorigin);
141
142 if (present & 4)
143 in_uint8(s, brush->style);
144
145 if (present & 8)
146 in_uint8(s, brush->pattern[0]);
147
148 if (present & 16)
149 in_uint8a(s, &brush->pattern[1], 7);
150
151 return s_check(s);
152}
153
154/* Process a destination blt order */
155static void
156process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta)
157{
158 if (present & 0x01)
159 rdp_in_coord(s, &os->x, delta);
160
161 if (present & 0x02)
162 rdp_in_coord(s, &os->y, delta);
163
164 if (present & 0x04)
165 rdp_in_coord(s, &os->cx, delta);
166
167 if (present & 0x08)
168 rdp_in_coord(s, &os->cy, delta);
169
170 if (present & 0x10)
171 in_uint8(s, os->opcode);
172
173 DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
174 os->opcode, os->x, os->y, os->cx, os->cy));
175
176 ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
177}
178
179/* Process a pattern blt order */
180static void
181process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta)
182{
183 if (present & 0x0001)
184 rdp_in_coord(s, &os->x, delta);
185
186 if (present & 0x0002)
187 rdp_in_coord(s, &os->y, delta);
188
189 if (present & 0x0004)
190 rdp_in_coord(s, &os->cx, delta);
191
192 if (present & 0x0008)
193 rdp_in_coord(s, &os->cy, delta);
194
195 if (present & 0x0010)
196 in_uint8(s, os->opcode);
197
198 if (present & 0x0020)
199 rdp_in_colour(s, &os->bgcolour);
200
201 if (present & 0x0040)
202 rdp_in_colour(s, &os->fgcolour);
203
204 rdp_parse_brush(s, &os->brush, present >> 7);
205
206 DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os->opcode, os->x,
207 os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour));
208
209 ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
210 &os->brush, os->bgcolour, os->fgcolour);
211}
212
213/* Process a screen blt order */
214static void
215process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta)
216{
217 if (present & 0x0001)
218 rdp_in_coord(s, &os->x, delta);
219
220 if (present & 0x0002)
221 rdp_in_coord(s, &os->y, delta);
222
223 if (present & 0x0004)
224 rdp_in_coord(s, &os->cx, delta);
225
226 if (present & 0x0008)
227 rdp_in_coord(s, &os->cy, delta);
228
229 if (present & 0x0010)
230 in_uint8(s, os->opcode);
231
232 if (present & 0x0020)
233 rdp_in_coord(s, &os->srcx, delta);
234
235 if (present & 0x0040)
236 rdp_in_coord(s, &os->srcy, delta);
237
238 DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
239 os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy));
240
241 ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
242}
243
244/* Process a line order */
245static void
246process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta)
247{
248 if (present & 0x0001)
249 in_uint16_le(s, os->mixmode);
250
251 if (present & 0x0002)
252 rdp_in_coord(s, &os->startx, delta);
253
254 if (present & 0x0004)
255 rdp_in_coord(s, &os->starty, delta);
256
257 if (present & 0x0008)
258 rdp_in_coord(s, &os->endx, delta);
259
260 if (present & 0x0010)
261 rdp_in_coord(s, &os->endy, delta);
262
263 if (present & 0x0020)
264 rdp_in_colour(s, &os->bgcolour);
265
266 if (present & 0x0040)
267 in_uint8(s, os->opcode);
268
269 rdp_parse_pen(s, &os->pen, present >> 7);
270
271 DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dx=%d,fg=0x%x)\n",
272 os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour));
273
274 if (os->opcode < 0x01 || os->opcode > 0x10)
275 {
276 error("bad ROP2 0x%x\n", os->opcode);
277 return;
278 }
279
280 ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen);
281}
282
283/* Process an opaque rectangle order */
284static void
285process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta)
286{
287 uint32 i;
288 if (present & 0x01)
289 rdp_in_coord(s, &os->x, delta);
290
291 if (present & 0x02)
292 rdp_in_coord(s, &os->y, delta);
293
294 if (present & 0x04)
295 rdp_in_coord(s, &os->cx, delta);
296
297 if (present & 0x08)
298 rdp_in_coord(s, &os->cy, delta);
299
300 if (present & 0x10)
301 {
302 in_uint8(s, i);
303 os->colour = (os->colour & 0xffffff00) | i;
304 }
305
306 if (present & 0x20)
307 {
308 in_uint8(s, i);
309 os->colour = (os->colour & 0xffff00ff) | (i << 8);
310 }
311
312 if (present & 0x40)
313 {
314 in_uint8(s, i);
315 os->colour = (os->colour & 0xff00ffff) | (i << 16);
316 }
317
318 DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour));
319
320 ui_rect(os->x, os->y, os->cx, os->cy, os->colour);
321}
322
323/* Process a desktop save order */
324static void
325process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta)
326{
327 int width, height;
328
329 if (present & 0x01)
330 in_uint32_le(s, os->offset);
331
332 if (present & 0x02)
333 rdp_in_coord(s, &os->left, delta);
334
335 if (present & 0x04)
336 rdp_in_coord(s, &os->top, delta);
337
338 if (present & 0x08)
339 rdp_in_coord(s, &os->right, delta);
340
341 if (present & 0x10)
342 rdp_in_coord(s, &os->bottom, delta);
343
344 if (present & 0x20)
345 in_uint8(s, os->action);
346
347 DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
348 os->left, os->top, os->right, os->bottom, os->offset, os->action));
349
350 width = os->right - os->left + 1;
351 height = os->bottom - os->top + 1;
352
353 if (os->action == 0)
354 ui_desktop_save(os->offset, os->left, os->top, width, height);
355 else
356 ui_desktop_restore(os->offset, os->left, os->top, width, height);
357}
358
359/* Process a memory blt order */
360static void
361process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta)
362{
363 HBITMAP bitmap;
364
365 if (present & 0x0001)
366 {
367 in_uint8(s, os->cache_id);
368 in_uint8(s, os->colour_table);
369 }
370
371 if (present & 0x0002)
372 rdp_in_coord(s, &os->x, delta);
373
374 if (present & 0x0004)
375 rdp_in_coord(s, &os->y, delta);
376
377 if (present & 0x0008)
378 rdp_in_coord(s, &os->cx, delta);
379
380 if (present & 0x0010)
381 rdp_in_coord(s, &os->cy, delta);
382
383 if (present & 0x0020)
384 in_uint8(s, os->opcode);
385
386 if (present & 0x0040)
387 rdp_in_coord(s, &os->srcx, delta);
388
389 if (present & 0x0080)
390 rdp_in_coord(s, &os->srcy, delta);
391
392 if (present & 0x0100)
393 in_uint16_le(s, os->cache_idx);
394
395 DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
396 os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx));
397
398 bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
399 if (bitmap == NULL)
400 return;
401
402 ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy);
403}
404
405/* Process a 3-way blt order */
406static void
407process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta)
408{
409 HBITMAP bitmap;
410
411 if (present & 0x000001)
412 {
413 in_uint8(s, os->cache_id);
414 in_uint8(s, os->colour_table);
415 }
416
417 if (present & 0x000002)
418 rdp_in_coord(s, &os->x, delta);
419
420 if (present & 0x000004)
421 rdp_in_coord(s, &os->y, delta);
422
423 if (present & 0x000008)
424 rdp_in_coord(s, &os->cx, delta);
425
426 if (present & 0x000010)
427 rdp_in_coord(s, &os->cy, delta);
428
429 if (present & 0x000020)
430 in_uint8(s, os->opcode);
431
432 if (present & 0x000040)
433 rdp_in_coord(s, &os->srcx, delta);
434
435 if (present & 0x000080)
436 rdp_in_coord(s, &os->srcy, delta);
437
438 if (present & 0x000100)
439 rdp_in_colour(s, &os->bgcolour);
440
441 if (present & 0x000200)
442 rdp_in_colour(s, &os->fgcolour);
443
444 rdp_parse_brush(s, &os->brush, present >> 10);
445
446 if (present & 0x008000)
447 in_uint16_le(s, os->cache_idx);
448
449 if (present & 0x010000)
450 in_uint16_le(s, os->unknown);
451
452 DEBUG(("TRIBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
453 os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx,
454 os->brush.style, os->bgcolour, os->fgcolour));
455
456 bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
457 if (bitmap == NULL)
458 return;
459
460 ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
461 bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour);
462}
463
464/* Parse a delta co-ordinate in polyline order form */
465static int
466parse_delta(uint8 * buffer, int *offset)
467{
468 int value = buffer[(*offset)++];
469 int two_byte = value & 0x80;
470
471 if (value & 0x40)/* sign bit */
472 value |= ~0x3f;
473 else
474 value &= 0x3f;
475
476 if (two_byte)
477 value = (value << 8) | buffer[(*offset)++];
478
479 return value;
480}
481
482/* Process a polyline order */
483static void
484process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
485{
486 int index, line, data;
487 int x, y, xfrom, yfrom;
488 uint8 flags = 0;
489 PEN pen;
490 uint8 opcode;
491
492 if (present & 0x01)
493 rdp_in_coord(s, &os->x, delta);
494
495 if (present & 0x02)
496 rdp_in_coord(s, &os->y, delta);
497
498 if (present & 0x04)
499 in_uint8(s, os->opcode);
500
501 if (present & 0x10)
502 rdp_in_colour(s, &os->fgcolour);
503
504 if (present & 0x20)
505 in_uint8(s, os->lines);
506
507 if (present & 0x40)
508 {
509 in_uint8(s, os->datasize);
510 in_uint8a(s, os->data, os->datasize);
511 }
512
513 DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
514 os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize));
515
516 DEBUG(("Data: "));
517
518 for (index = 0; index < os->datasize; index++)
519 DEBUG(("%02x ", os->data[index]));
520
521 DEBUG(("\n"));
522
523 if (os->opcode < 0x01 || os->opcode > 0x10)
524 {
525 error("bad ROP2 0x%x\n", os->opcode);
526 return;
527 }
528
529 opcode = os->opcode - 1;
530 x = os->x;
531 y = os->y;
532 pen.style = pen.width = 0;
533 pen.colour = os->fgcolour;
534
535 index = 0;
536 data = ((os->lines - 1) / 4) + 1;
537 for (line = 0; (line < os->lines) && (data < os->datasize); line++)
538 {
539 xfrom = x;
540 yfrom = y;
541
542 if (line % 4 == 0)
543 flags = os->data[index++];
544
545 if ((flags & 0xc0) == 0)
546 flags |= 0xc0;/* none = both */
547
548 if (flags & 0x40)
549 x += parse_delta(os->data, &data);
550
551 if (flags & 0x80)
552 y += parse_delta(os->data, &data);
553
554 ui_line(opcode, xfrom, yfrom, x, y, &pen);
555
556 flags <<= 2;
557 }
558}
559
560/* Process a text order */
561static void
562process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta)
563{
564 int i;
565
566 if (present & 0x000001)
567 in_uint8(s, os->font);
568
569 if (present & 0x000002)
570 in_uint8(s, os->flags);
571
572 if (present & 0x000004)
573 in_uint8(s, os->unknown);
574
575 if (present & 0x000008)
576 in_uint8(s, os->mixmode);
577
578 if (present & 0x000010)
579 rdp_in_colour(s, &os->fgcolour);
580
581 if (present & 0x000020)
582 rdp_in_colour(s, &os->bgcolour);
583
584 if (present & 0x000040)
585 in_uint16_le(s, os->clipleft);
586
587 if (present & 0x000080)
588 in_uint16_le(s, os->cliptop);
589
590 if (present & 0x000100)
591 in_uint16_le(s, os->clipright);
592
593 if (present & 0x000200)
594 in_uint16_le(s, os->clipbottom);
595
596 if (present & 0x000400)
597 in_uint16_le(s, os->boxleft);
598
599 if (present & 0x000800)
600 in_uint16_le(s, os->boxtop);
601
602 if (present & 0x001000)
603 in_uint16_le(s, os->boxright);
604
605 if (present & 0x002000)
606 in_uint16_le(s, os->boxbottom);
607
608 if (present & 0x004000) /* fix for connecting to a server that */
609 in_uint8s(s, 10); /* was disconnected with mstsc.exe */
610 /* 0x008000, 0x020000, and 0x040000 are present too ??? */
611
612 if (present & 0x080000)
613 in_uint16_le(s, os->x);
614
615 if (present & 0x100000)
616 in_uint16_le(s, os->y);
617
618 if (present & 0x200000)
619 {
620 in_uint8(s, os->length);
621 in_uint8a(s, os->text, os->length);
622 }
623
624 DEBUG(("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,bb=%d,br=%d,fg=0x%x,bg=0x%x,font=%d,fl=0x%x,mix=%d,unk=0x%x,n=%d)\n", os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft, os->boxtop, os->boxright, os->boxbottom, os->fgcolour, os->bgcolour, os->font, os->flags, os->mixmode, os->unknown, os->length));
625
626 DEBUG(("Text: "));
627
628 for (i = 0; i < os->length; i++)
629 DEBUG(("%02x ", os->text[i]));
630
631 DEBUG(("\n"));
632
633 ui_draw_text(os->font, os->flags, os->mixmode, os->x, os->y,
634 os->clipleft, os->cliptop,
635 os->clipright - os->clipleft,
636 os->clipbottom - os->cliptop,
637 os->boxleft, os->boxtop,
638 os->boxright - os->boxleft,
639 os->boxbottom - os->boxtop, os->bgcolour, os->fgcolour, os->text, os->length);
640}
641
642/* Process a raw bitmap cache order */
643static void
644process_raw_bmpcache(STREAM s)
645{
646 HBITMAP bitmap;
647 uint16 cache_idx, bufsize;
648 uint8 cache_id, width, height, bpp, Bpp;
649 uint8 *data, *inverted;
650 int y;
651
652 in_uint8(s, cache_id);
653 in_uint8s(s, 1);/* pad */
654 in_uint8(s, width);
655 in_uint8(s, height);
656 in_uint8(s, bpp);
657 Bpp = (bpp + 7) / 8;
658 in_uint16_le(s, bufsize);
659 in_uint16_le(s, cache_idx);
660 in_uint8p(s, data, bufsize);
661
662 DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
663 inverted = (uint8*)xmalloc(width * height * Bpp);
664 for (y = 0; y < height; y++)
665 {
666 memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)],
667 width * Bpp);
668 }
669
670 bitmap = ui_create_bitmap(width, height, inverted);
671 xfree(inverted);
672 cache_put_bitmap(cache_id, cache_idx, bitmap);
673}
674
675/* Process a bitmap cache order */
676static void
677process_bmpcache(STREAM s)
678{
679 HBITMAP bitmap;
680 uint16 cache_idx, size;
681 uint8 cache_id, width, height, bpp, Bpp;
682 uint8 *data, *bmpdata;
683
684 in_uint8(s, cache_id);
685 in_uint8s(s, 1);/* pad */
686 in_uint8(s, width);
687 in_uint8(s, height);
688 in_uint8(s, bpp);
689 Bpp = (bpp + 7) / 8;
690 in_uint8s(s, 2);/* bufsize */
691 in_uint16_le(s, cache_idx);
692 in_uint8s(s, 2);/* pad */
693 in_uint16_le(s, size);
694 in_uint8s(s, 4);/* row_size, final_size */
695 in_uint8p(s, data, size);
696 DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
697 bmpdata = (uint8*)xmalloc(width * height * Bpp);
698 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
699 {
700 bitmap = ui_create_bitmap(width, height, bmpdata);
701 cache_put_bitmap(cache_id, cache_idx, bitmap);
702 }
703 xfree(bmpdata);
704}
705
706/* Process a colourmap cache order */
707static void
708process_colcache(STREAM s)
709{
710 COLOURENTRY *entry;
711 COLOURMAP map;
712 HCOLOURMAP hmap;
713 uint8 cache_id;
714 int i;
715 in_uint8(s, cache_id);
716 in_uint16_le(s, map.ncolours);
717
718 map.colours = (COLOURENTRY*)xmalloc(3 * map.ncolours);
719
720 for (i = 0; i < map.ncolours; i++)
721 {
722 entry = &map.colours[i];
723 in_uint8(s, entry->blue);
724 in_uint8(s, entry->green);
725 in_uint8(s, entry->red);
726 in_uint8s(s, 1);/* pad */
727 }
728
729 DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours));
730
731 hmap = ui_create_colourmap(&map);
732 ui_set_colourmap(hmap);
733
734 xfree(map.colours);
735}
736
737/* Process a font cache order */
738static void
739process_fontcache(STREAM s)
740{
741 HGLYPH bitmap;
742 uint8 font, nglyphs;
743 uint16 character, offset, baseline, width, height;
744 int i, datasize;
745 uint8 *data;
746
747 in_uint8(s, font);
748 in_uint8(s, nglyphs);
749
750 DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs));
751
752 for (i = 0; i < nglyphs; i++)
753 {
754 in_uint16_le(s, character);
755 in_uint16_le(s, offset);
756 in_uint16_le(s, baseline);
757 in_uint16_le(s, width);
758 in_uint16_le(s, height);
759
760 datasize = (height * ((width + 7) / 8) + 3) & ~3;
761 in_uint8p(s, data, datasize);
762
763 bitmap = ui_create_glyph(width, height, data);
764 cache_put_font(font, character, offset, baseline, width, height, bitmap);
765 }
766}
767
768/* Process a secondary order */
769static void
770process_secondary_order(STREAM s)
771{
772 uint16 length;
773 uint8 type;
774 uint8 *next_order;
775
776 in_uint16_le(s, length);
777 in_uint8s(s, 2);/* flags */
778 in_uint8(s, type);
779
780 next_order = s->p + length + 7;
781
782 switch (type)
783 {
784 case RDP_ORDER_RAW_BMPCACHE:
785 process_raw_bmpcache(s);
786 break;
787
788 case RDP_ORDER_COLCACHE:
789 process_colcache(s);
790 break;
791
792 case RDP_ORDER_BMPCACHE:
793 process_bmpcache(s);
794 break;
795
796 case RDP_ORDER_FONTCACHE:
797 process_fontcache(s);
798 break;
799
800 default:
801 unimpl("secondary order %d\n", type);
802 }
803
804 s->p = next_order;
805}
806
807/* Process an order PDU */
808void
809process_orders(STREAM s)
810{
811 RDP_ORDER_STATE *os = &order_state;
812 uint32 present;
813 uint16 num_orders;
814 uint8 order_flags;
815 int size, processed = 0;
816 BOOL delta;
817
818 in_uint8s(s, 2);/* pad */
819 in_uint16_le(s, num_orders);
820 in_uint8s(s, 2);/* pad */
821
822 while (processed < num_orders)
823 {
824 in_uint8(s, order_flags);
825
826 if (!(order_flags & RDP_ORDER_STANDARD))
827 {
828 error("order parsing failed\n");
829 break;
830 }
831
832 if (order_flags & RDP_ORDER_SECONDARY)
833 {
834 process_secondary_order(s);
835 }
836 else
837 {
838 if (order_flags & RDP_ORDER_CHANGE)
839 {
840 in_uint8(s, os->order_type);
841 }
842
843 switch (os->order_type)
844 {
845 case RDP_ORDER_TRIBLT:
846 case RDP_ORDER_TEXT2:
847 size = 3;
848 break;
849
850 case RDP_ORDER_PATBLT:
851 case RDP_ORDER_MEMBLT:
852 case RDP_ORDER_LINE:
853 size = 2;
854 break;
855
856 default:
857 size = 1;
858 }
859
860 rdp_in_present(s, &present, order_flags, size);
861
862 if (order_flags & RDP_ORDER_BOUNDS)
863 {
864 if (!(order_flags & RDP_ORDER_LASTBOUNDS))
865 rdp_parse_bounds(s, &os->bounds);
866
867 ui_set_clip(os->bounds.left,
868 os->bounds.top,
869 os->bounds.right -
870 os->bounds.left + 1,
871 os->bounds.bottom - os->bounds.top + 1);
872 }
873
874 delta = order_flags & RDP_ORDER_DELTA;
875
876 switch (os->order_type)
877 {
878 case RDP_ORDER_DESTBLT:
879 process_destblt(s, &os->destblt, present, delta);
880 break;
881
882 case RDP_ORDER_PATBLT:
883 process_patblt(s, &os->patblt, present, delta);
884 break;
885
886 case RDP_ORDER_SCREENBLT:
887 process_screenblt(s, &os->screenblt, present, delta);
888 break;
889
890 case RDP_ORDER_LINE:
891 process_line(s, &os->line, present, delta);
892 break;
893
894 case RDP_ORDER_RECT:
895 process_rect(s, &os->rect, present, delta);
896 break;
897
898 case RDP_ORDER_DESKSAVE:
899 process_desksave(s, &os->desksave, present, delta);
900 break;
901
902 case RDP_ORDER_MEMBLT:
903 process_memblt(s, &os->memblt, present, delta);
904 break;
905
906 case RDP_ORDER_TRIBLT:
907 process_triblt(s, &os->triblt, present, delta);
908 break;
909
910 case RDP_ORDER_POLYLINE:
911 process_polyline(s, &os->polyline, present, delta);
912 break;
913
914 case RDP_ORDER_TEXT2:
915 process_text2(s, &os->text2, present, delta);
916 break;
917
918 default:
919 unimpl("order %d\n", os->order_type);
920 return;
921 }
922
923 if (order_flags & RDP_ORDER_BOUNDS)
924 ui_reset_clip();
925 }
926
927 processed++;
928 }
929
930 if (s->p != next_packet)
931 error("%d bytes remaining\n", (int) (next_packet - s->p));
932}
933
934/* Reset order state */
935void
936reset_order_state(void)
937{
938 memset(&order_state, 0, sizeof(order_state));
939 order_state.order_type = RDP_ORDER_PATBLT;
940}
diff --git a/noncore/net/opierdesktop/orders.h b/noncore/net/opierdesktop/orders.h
new file mode 100644
index 0000000..be862c6
--- a/dev/null
+++ b/noncore/net/opierdesktop/orders.h
@@ -0,0 +1,286 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 RDP order processing
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#define RDP_ORDER_STANDARD 0x01
22#define RDP_ORDER_SECONDARY 0x02
23#define RDP_ORDER_BOUNDS 0x04
24#define RDP_ORDER_CHANGE 0x08
25#define RDP_ORDER_DELTA 0x10
26#define RDP_ORDER_LASTBOUNDS 0x20
27#define RDP_ORDER_SMALL 0x40
28#define RDP_ORDER_TINY 0x80
29
30enum RDP_ORDER_TYPE
31{
32 RDP_ORDER_DESTBLT = 0,
33 RDP_ORDER_PATBLT = 1,
34 RDP_ORDER_SCREENBLT = 2,
35 RDP_ORDER_LINE = 9,
36 RDP_ORDER_RECT = 10,
37 RDP_ORDER_DESKSAVE = 11,
38 RDP_ORDER_MEMBLT = 13,
39 RDP_ORDER_TRIBLT = 14,
40 RDP_ORDER_POLYLINE = 22,
41 RDP_ORDER_TEXT2 = 27
42};
43
44enum RDP_SECONDARY_ORDER_TYPE
45{
46 RDP_ORDER_RAW_BMPCACHE = 0,
47 RDP_ORDER_COLCACHE = 1,
48 RDP_ORDER_BMPCACHE = 2,
49 RDP_ORDER_FONTCACHE = 3
50};
51
52typedef struct _DESTBLT_ORDER
53{
54 sint16 x;
55 sint16 y;
56 sint16 cx;
57 sint16 cy;
58 uint8 opcode;
59
60}
61DESTBLT_ORDER;
62
63typedef struct _PATBLT_ORDER
64{
65 sint16 x;
66 sint16 y;
67 sint16 cx;
68 sint16 cy;
69 uint8 opcode;
70 uint32 bgcolour;
71 uint32 fgcolour;
72 BRUSH brush;
73
74}
75PATBLT_ORDER;
76
77typedef struct _SCREENBLT_ORDER
78{
79 sint16 x;
80 sint16 y;
81 sint16 cx;
82 sint16 cy;
83 uint8 opcode;
84 sint16 srcx;
85 sint16 srcy;
86
87}
88SCREENBLT_ORDER;
89
90typedef struct _LINE_ORDER
91{
92 uint16 mixmode;
93 sint16 startx;
94 sint16 starty;
95 sint16 endx;
96 sint16 endy;
97 uint32 bgcolour;
98 uint8 opcode;
99 PEN pen;
100
101}
102LINE_ORDER;
103
104typedef struct _RECT_ORDER
105{
106 sint16 x;
107 sint16 y;
108 sint16 cx;
109 sint16 cy;
110 uint32 colour;
111
112}
113RECT_ORDER;
114
115typedef struct _DESKSAVE_ORDER
116{
117 uint32 offset;
118 sint16 left;
119 sint16 top;
120 sint16 right;
121 sint16 bottom;
122 uint8 action;
123
124}
125DESKSAVE_ORDER;
126
127typedef struct _TRIBLT_ORDER
128{
129 uint8 colour_table;
130 uint8 cache_id;
131 sint16 x;
132 sint16 y;
133 sint16 cx;
134 sint16 cy;
135 uint8 opcode;
136 sint16 srcx;
137 sint16 srcy;
138 uint32 bgcolour;
139 uint32 fgcolour;
140 BRUSH brush;
141 uint16 cache_idx;
142 uint16 unknown;
143
144}
145TRIBLT_ORDER;
146
147typedef struct _MEMBLT_ORDER
148{
149 uint8 colour_table;
150 uint8 cache_id;
151 sint16 x;
152 sint16 y;
153 sint16 cx;
154 sint16 cy;
155 uint8 opcode;
156 sint16 srcx;
157 sint16 srcy;
158 uint16 cache_idx;
159
160}
161MEMBLT_ORDER;
162
163#define MAX_DATA 256
164
165typedef struct _POLYLINE_ORDER
166{
167 sint16 x;
168 sint16 y;
169 uint8 opcode;
170 uint32 fgcolour;
171 uint8 lines;
172 uint8 datasize;
173 uint8 data[MAX_DATA];
174
175}
176POLYLINE_ORDER;
177
178#define MAX_TEXT 256
179
180typedef struct _TEXT2_ORDER
181{
182 uint8 font;
183 uint8 flags;
184 uint8 mixmode;
185 uint8 unknown;
186 uint32 fgcolour;
187 uint32 bgcolour;
188 sint16 clipleft;
189 sint16 cliptop;
190 sint16 clipright;
191 sint16 clipbottom;
192 sint16 boxleft;
193 sint16 boxtop;
194 sint16 boxright;
195 sint16 boxbottom;
196 sint16 x;
197 sint16 y;
198 uint8 length;
199 uint8 text[MAX_TEXT];
200
201}
202TEXT2_ORDER;
203
204typedef struct _RDP_ORDER_STATE
205{
206 uint8 order_type;
207 BOUNDS bounds;
208
209 DESTBLT_ORDER destblt;
210 PATBLT_ORDER patblt;
211 SCREENBLT_ORDER screenblt;
212 LINE_ORDER line;
213 RECT_ORDER rect;
214 DESKSAVE_ORDER desksave;
215 MEMBLT_ORDER memblt;
216 TRIBLT_ORDER triblt;
217 POLYLINE_ORDER polyline;
218 TEXT2_ORDER text2;
219
220}
221RDP_ORDER_STATE;
222
223typedef struct _RDP_RAW_BMPCACHE_ORDER
224{
225 uint8 cache_id;
226 uint8 pad1;
227 uint8 width;
228 uint8 height;
229 uint8 bpp;
230 uint16 bufsize;
231 uint16 cache_idx;
232 uint8 *data;
233
234}
235RDP_RAW_BMPCACHE_ORDER;
236
237typedef struct _RDP_BMPCACHE_ORDER
238{
239 uint8 cache_id;
240 uint8 pad1;
241 uint8 width;
242 uint8 height;
243 uint8 bpp;
244 uint16 bufsize;
245 uint16 cache_idx;
246 uint16 pad2;
247 uint16 size;
248 uint16 row_size;
249 uint16 final_size;
250 uint8 *data;
251
252}
253RDP_BMPCACHE_ORDER;
254
255#define MAX_GLYPH 32
256
257typedef struct _RDP_FONT_GLYPH
258{
259 uint16 character;
260 uint16 unknown;
261 uint16 baseline;
262 uint16 width;
263 uint16 height;
264 uint8 data[MAX_GLYPH];
265
266}
267RDP_FONT_GLYPH;
268
269#define MAX_GLYPHS 256
270
271typedef struct _RDP_FONTCACHE_ORDER
272{
273 uint8 font;
274 uint8 nglyphs;
275 RDP_FONT_GLYPH glyphs[MAX_GLYPHS];
276
277}
278RDP_FONTCACHE_ORDER;
279
280typedef struct _RDP_COLCACHE_ORDER
281{
282 uint8 cache_id;
283 COLOURMAP map;
284
285}
286RDP_COLCACHE_ORDER;
diff --git a/noncore/net/opierdesktop/parse.h b/noncore/net/opierdesktop/parse.h
new file mode 100644
index 0000000..f54c05f
--- a/dev/null
+++ b/noncore/net/opierdesktop/parse.h
@@ -0,0 +1,108 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Parsing primitives
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21/* Parser state */
22typedef struct stream
23{
24 unsigned char *p;
25 unsigned char *end;
26 unsigned char *data;
27 unsigned int size;
28 //unsigned char *next_packet;
29
30
31 /* Offsets of various headers */
32 unsigned char *iso_hdr;
33 unsigned char *mcs_hdr;
34 unsigned char *sec_hdr;
35 unsigned char *rdp_hdr;
36
37}
38 *STREAM;
39
40 #define s_push_layer(s,h,n){ (s)->h = (s)->p; (s)->p += n; }
41 #define s_pop_layer(s,h)(s)->p = (s)->h;
42 #define s_mark_end(s) (s)->end = (s)->p;
43 #define s_check(s) ((s)->p <= (s)->end)
44 #define s_check_rem(s,n)((s)->p + n <= (s)->end)
45 #define s_check_end(s) ((s)->p == (s)->end)
46
47#if defined(L_ENDIAN) && !defined(NEED_ALIGN)
48 #define in_uint16_le(s,v){ v = *(uint16 *)((s)->p); (s)->p += 2; }
49 #define in_uint32_le(s,v){ v = *(uint32 *)((s)->p); (s)->p += 4; }
50 #define out_uint16_le(s,v){ *(uint16 *)((s)->p) = v; (s)->p += 2; }
51 #define out_uint32_le(s,v){ *(uint32 *)((s)->p) = v; (s)->p += 4; }
52
53#else
54 #define in_uint16_le(s,v){ v = *((s)->p++); v += *((s)->p++) << 8; }
55 #define in_uint32_le(s,v){ in_uint16_le(s,v) \
56 v += *((s)->p++) << 16; v += *((s)->p++) << 24; }
57 #define out_uint16_le(s,v){ *((s)->p++) = (v) & 0xff; *((s)->p++) = ((v) >> 8) & 0xff; }
58 #define out_uint32_le(s,v){ out_uint16_le(s, (v) & 0xffff); out_uint16_le(s, ((v) >> 16) & 0xffff); }
59#endif
60
61#if defined(B_ENDIAN) && !defined(NEED_ALIGN)
62 #define in_uint16_be(s,v){ v = *(uint16 *)((s)->p); (s)->p += 2; }
63 #define in_uint32_be(s,v){ v = *(uint32 *)((s)->p); (s)->p += 4; }
64 #define out_uint16_be(s,v){ *(uint16 *)((s)->p) = v; (s)->p += 2; }
65 #define out_uint32_be(s,v){ *(uint32 *)((s)->p) = v; (s)->p += 4; }
66
67#define B_ENDIAN_PREFERRED
68 #define in_uint16(s,v) in_uint16_be(s,v)
69 #define in_uint32(s,v) in_uint32_be(s,v)
70 #define out_uint16(s,v) out_uint16_be(s,v)
71 #define out_uint32(s,v) out_uint32_be(s,v)
72
73#else
74 #define next_be(s,v) v = ((v) << 8) + *((s)->p++);
75 #define in_uint16_be(s,v){ v = *((s)->p++); next_be(s,v); }
76 #define in_uint32_be(s,v){ in_uint16_be(s,v); next_be(s,v); next_be(s,v); }
77 #define out_uint16_be(s,v){ *((s)->p++) = ((v) >> 8) & 0xff; *((s)->p++) = (v) & 0xff; }
78 #define out_uint32_be(s,v){ out_uint16_be(s, ((v) >> 16) & 0xffff); out_uint16_be(s, (v) & 0xffff); }
79#endif
80
81#ifndef B_ENDIAN_PREFERRED
82 #define in_uint16(s,v) in_uint16_le(s,v)
83 #define in_uint32(s,v) in_uint32_le(s,v)
84 #define out_uint16(s,v) out_uint16_le(s,v)
85 #define out_uint32(s,v) out_uint32_le(s,v)
86#endif
87
88 #define in_uint8(s,v) v = *((s)->p++);
89 #define in_uint8p(s,v,n){ v = (s)->p; (s)->p += n; }
90 #define in_uint8a(s,v,n){ memcpy(v,(s)->p,n); (s)->p += n; }
91 #define in_uint8s(s,n) (s)->p += n;
92 #define out_uint8(s,v) *((s)->p++) = v;
93 #define out_uint8p(s,v,n){ memcpy((s)->p,v,n); (s)->p += n; }
94 #define out_uint8a(s,v,n)out_uint8p(s,v,n);
95 #define out_uint8s(s,n) { memset((s)->p,0,n); (s)->p += n; }
96
97#if defined(B_ENDIAN)
98
99#endif
100#if defined(B_ENDIAN_PREFERRED)
101
102#endif
103#if defined(NEED_ALIGN)
104
105#endif
106#if defined(L_ENDIAN)
107
108#endif
diff --git a/noncore/net/opierdesktop/proto.h b/noncore/net/opierdesktop/proto.h
new file mode 100644
index 0000000..6bc5b13
--- a/dev/null
+++ b/noncore/net/opierdesktop/proto.h
@@ -0,0 +1,121 @@
1/* bitmap.c */
2BOOL bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size,
3 int Bpp);
4/* cache.c */
5HBITMAP cache_get_bitmap(uint8 cache_id, uint16 cache_idx);
6void cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap);
7FONTGLYPH *cache_get_font(uint8 font, uint16 character);
8void cache_put_font(uint8 font, uint16 character, uint16 offset, uint16 baseline, uint16 width,
9 uint16 height, HGLYPH pixmap);
10DATABLOB *cache_get_text(uint8 cache_id);
11void cache_put_text(uint8 cache_id, void *data, int length);
12uint8 *cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel);
13void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel,
14 uint8 * data);
15HCURSOR cache_get_cursor(uint16 cache_idx);
16void cache_put_cursor(uint16 cache_idx, HCURSOR cursor);
17/* ewmhints.c */
18int get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height);
19/* iso.c */
20STREAM iso_init(int length);
21void iso_send(STREAM s);
22STREAM iso_recv(void);
23BOOL iso_connect(char *server);
24void iso_disconnect(void);
25/* licence.c */
26void licence_process(STREAM s);
27/* mcs.c */
28STREAM mcs_init(int length);
29void mcs_send(STREAM s);
30STREAM mcs_recv(void);
31BOOL mcs_connect(char *server, STREAM mcs_data);
32void mcs_disconnect(void);
33/* orders.c */
34void process_orders(STREAM s);
35void reset_order_state(void);
36/* rdesktop.c */
37int main(int argc, char *argv[]);
38void generate_random(uint8 * random);
39void *xmalloc(int size);
40void *xrealloc(void *oldmem, int size);
41void xfree(void *mem);
42void error(char *format, ...);
43void warning(char *format, ...);
44void unimpl(char *format, ...);
45void hexdump(unsigned char *p, unsigned int len);
46int load_licence(unsigned char **data);
47void save_licence(unsigned char *data, int length);
48/* rdp.c */
49void rdp_out_unistr(STREAM s, char *string, int len);
50void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1,
51 uint16 param2);
52BOOL rdp_main_loop(void);
53BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, char *command,
54 char *directory);
55void rdp_disconnect(void);
56/* secure.c */
57void sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt);
58void sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2);
59void buf_out_uint32(uint8 * buffer, uint32 value);
60void sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data,
61 int datalen);
62STREAM sec_init(uint32 flags, int maxlen);
63void sec_send(STREAM s, uint32 flags);
64STREAM sec_recv(void);
65BOOL sec_connect(char *server);
66void sec_disconnect(void);
67/* tcp.c */
68STREAM tcp_init(unsigned int maxlen);
69void tcp_send(STREAM s);
70STREAM tcp_recv(unsigned int length);
71BOOL tcp_connect(char *server);
72void tcp_disconnect(void);
73/* xkeymap.c */
74void xkeymap_init(void);
75BOOL handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed);
76key_translation xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state);
77uint16 xkeymap_translate_button(unsigned int button);
78char *get_ksname(uint32 keysym);
79void ensure_remote_modifiers(uint32 ev_time, key_translation tr);
80void reset_modifier_keys(unsigned int state);
81void rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode);
82/* xwin.c */
83BOOL get_key_state(unsigned int state, uint32 keysym);
84BOOL ui_init(void);
85void ui_deinit(void);
86BOOL ui_create_window(void);
87void ui_destroy_window(void);
88void xwin_toggle_fullscreen(void);
89int ui_select(int rdp_socket);
90void ui_move_pointer(int x, int y);
91HBITMAP ui_create_bitmap(int width, int height, uint8 * data);
92void ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data);
93void ui_destroy_bitmap(HBITMAP bmp);
94HGLYPH ui_create_glyph(int width, int height, uint8 * data);
95void ui_destroy_glyph(HGLYPH glyph);
96HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask,
97 uint8 * xormask);
98void ui_set_cursor(HCURSOR cursor);
99void ui_destroy_cursor(HCURSOR cursor);
100HCOLOURMAP ui_create_colourmap(COLOURMAP * colours);
101void ui_destroy_colourmap(HCOLOURMAP map);
102void ui_set_colourmap(HCOLOURMAP map);
103void ui_begin_update(void);
104void ui_end_update(void);
105void ui_set_clip(int x, int y, int cx, int cy);
106void ui_reset_clip(void);
107void ui_bell(void);
108void ui_destblt(uint8 opcode, int x, int y, int cx, int cy);
109void ui_patblt(uint8 opcode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour,
110 int fgcolour);
111void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy);
112void ui_memblt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy);
113void ui_triblt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy,
114 BRUSH * brush, int bgcolour, int fgcolour);
115void ui_line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen);
116void ui_rect(int x, int y, int cx, int cy, int colour);
117void ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y, int clipx, int clipy,
118 int clipcx, int clipcy, int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
119 int fgcolour, uint8 * text, uint8 length);
120void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy);
121void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy);
diff --git a/noncore/net/opierdesktop/qtwin.cpp b/noncore/net/opierdesktop/qtwin.cpp
new file mode 100644
index 0000000..d2a5ef1
--- a/dev/null
+++ b/noncore/net/opierdesktop/qtwin.cpp
@@ -0,0 +1,1725 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - X Window System
4 Copyright (C) Matthew Chapman 1999-2002
5 qt.cpp by Jay Sorg
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "rdesktop.h"
23#ifdef SHARP
24#include <qpe/qpeapplication.h>
25#else
26#include <qapplication.h>
27#endif
28#include <qmainwindow.h>
29#include <qwidget.h>
30#include <qpainter.h>
31#include <qimage.h>
32#include <qsocketnotifier.h>
33#include <qscrollview.h>
34#include <qmessagebox.h>
35#include <qpushbutton.h>
36#include <qlineedit.h>
37#include <qcombobox.h>
38#include <qlabel.h>
39#include <qfile.h>
40#include <qcheckbox.h>
41#include <qpopupmenu.h>
42#include "qtwin.h"
43#include <stdlib.h>
44
45uint32 flags;
46char server[64] = "";
47char domain[16] = "";
48char password[16] = "";
49char shell[128] = "";
50char directory[32] = "";
51
52extern int g_width;
53extern int g_height;
54extern int server_bpp;
55extern BOOL fullscreen;
56extern char username[];
57int global_sock;
58
59QSocketNotifier* SocketNotifier;
60#ifdef SHARP
61QPEApplication* App;
62#else
63QApplication* App;
64#endif
65QMyMainWindow* MW;
66QMyScrollView* SV;
67struct QColorMap
68{
69 uint32 RGBColors[256];
70 int NumColors;
71};
72QColorMap* CM;
73uint8* BS;
74int clipx;
75int clipy;
76int clipcx;
77int clipcy;
78
79struct bitmap
80{
81 int w;
82 int h;
83 uint8* data;
84};
85
86BOOL owncolmap = False;
87
88//*****************************************************************************
89void CleanString(QString* Item)
90{
91 int i;
92
93 i = Item->length() - 1;
94 while (i >= 0)
95 {
96 if (Item->at(i) == 10 || Item->at(i) == 13)
97 Item->remove(i, 1);
98 i--;
99 }
100}
101
102//*****************************************************************************
103QMyDialog::QMyDialog(QWidget* parent) : QDialog(parent, "Settings", true)
104{
105 int i, j;
106 char* home;
107 char Text[256];
108 QString Line;
109 QString ItemName;
110 QString ItemValue;
111
112 // resize dialog
113 resize(230, 270);
114 // main list box
115 ListBox = new QListBox(this);
116 ListBox->move(10, 10);
117 ListBox->resize(200, 100);
118 connect(ListBox, SIGNAL(selectionChanged()), this, SLOT(ListBoxChanged()));
119 connect(ListBox, SIGNAL(selected(int)), this, SLOT(ListBoxSelected(int)));
120 // server
121 Label1 = new QLabel(this);
122 Label1->setText("Server Desc");
123 Label1->move(10, 120);
124 Label1->resize(100, 20);
125 ServerNameEdit = new QLineEdit(this);
126 ServerNameEdit->move(75, 120);
127 ServerNameEdit->resize(100, 20);
128 // username
129 Label2 = new QLabel(this);
130 Label2->setText("User Name");
131 Label2->move(10, 150);
132 Label2->resize(100, 20);
133 UserNameEdit = new QLineEdit(this);
134 UserNameEdit->move(75, 150);
135 UserNameEdit->resize(100, 20);
136 // ip
137 Label3 = new QLabel(this);
138 Label3->setText("Server IP");
139 Label3->move(10, 180);
140 Label3->resize(100, 20);
141 IPEdit = new QLineEdit(this);
142 IPEdit->move(75, 180);
143 IPEdit->resize(100, 20);
144 // width and height
145 WidthHeightBox = new QComboBox(this);
146 WidthHeightBox->move(10, 210);
147 WidthHeightBox->resize(100, 20);
148 WidthHeightBox->insertItem("240x320");
149 WidthHeightBox->insertItem("640x480");
150 WidthHeightBox->insertItem("800x600");
151 connect(WidthHeightBox, SIGNAL(activated(int)), this, SLOT(ComboChanged(int)));
152 WidthHeightBox->setCurrentItem(1);
153 WidthEdit = new QLineEdit(this);
154 WidthEdit->move(110, 210);
155 WidthEdit->resize(30, 20);
156 WidthEdit->setText("800");
157 HeightEdit = new QLineEdit(this);
158 HeightEdit->move(140, 210);
159 HeightEdit->resize(30, 20);
160 HeightEdit->setText("600");
161 // add to list button
162 AddButton = new QPushButton(this);
163 AddButton->move(180, 120);
164 AddButton->resize(50, 20);
165 AddButton->setText("Add");
166 connect(AddButton, SIGNAL(clicked()), this, SLOT(AddClicked()));
167 // change list item button
168 EditButton = new QPushButton(this);
169 EditButton->move(180, 140);
170 EditButton->resize(50, 20);
171 EditButton->setText("Edit");
172 connect(EditButton, SIGNAL(clicked()), this, SLOT(EditClicked()));
173 // save to file button
174 SaveButton = new QPushButton(this);
175 SaveButton->move(180, 160);
176 SaveButton->resize(50, 20);
177 SaveButton->setText("Save");
178 connect(SaveButton, SIGNAL(clicked()), this, SLOT(SaveClicked()));
179 // remove an item button
180 RemoveButton = new QPushButton(this);
181 RemoveButton->move(180, 180);
182 RemoveButton->resize(50, 20);
183 RemoveButton->setText("Remove");
184 connect(RemoveButton, SIGNAL(clicked()), this, SLOT(RemoveClicked()));
185 // full screen check box
186 FullScreenCheckBox = new QCheckBox(this, "Full Screen");
187 FullScreenCheckBox->setText("Full Screen");
188 FullScreenCheckBox->move(10, 230);
189 // ok button
190 OKButton = new QPushButton(this);
191 OKButton->setText("OK");
192 OKButton->move(100, 240);
193 OKButton->resize(50, 20);
194 connect(OKButton, SIGNAL(clicked()), this, SLOT(OKClicked()));
195 // cancel button
196 CancelButton = new QPushButton(this);
197 CancelButton->setText("Cancel");
198 CancelButton->move(160, 240);
199 CancelButton->resize(50, 20);
200 connect(CancelButton, SIGNAL(clicked()), this, SLOT(CancelClicked()));
201
202 for (i = 0; i < 10; i++)
203 {
204 ConnectionList[i] = new QMyConnectionItem;
205 ConnectionList[i]->ServerName = "";
206 ConnectionList[i]->UserName = "";
207 ConnectionList[i]->ServerIP = "";
208 ConnectionList[i]->Width = 0;
209 ConnectionList[i]->Height = 0;
210 ConnectionList[i]->FullScreen = 0;
211 }
212 home = getenv("HOME");
213 if (home != NULL)
214 {
215 sprintf(Text, "%s/rdesktop.ini", home);
216 QFile* File = new QFile(Text);
217 if (File->open(IO_ReadOnly))
218 {
219 i = -1;
220 while (!File->atEnd())
221 {
222 File->readLine(Line, 255);
223 j = Line.find("=");
224 if (j > 0)
225 {
226 ItemName = Line.mid(0, j);
227 CleanString(&ItemName);
228 ItemValue = Line.mid(j + 1);
229 CleanString(&ItemValue);
230 if (ItemName == "Server")
231 {
232 i++;
233 ConnectionList[i]->ServerName = ItemValue;
234 ListBox->insertItem(ItemValue);
235 }
236 else if (ItemName == "UserName")
237 ConnectionList[i]->UserName = ItemValue;
238 else if (ItemName == "Width")
239 ConnectionList[i]->Width = ItemValue.toInt();
240 else if (ItemName == "Height")
241 ConnectionList[i]->Height = ItemValue.toInt();
242 else if (ItemName == "IP")
243 ConnectionList[i]->ServerIP = ItemValue;
244 else if (ItemName == "FullScreen")
245 ConnectionList[i]->FullScreen = (ItemValue != "0");
246 }
247 }
248 }
249 delete File;
250 }
251}
252
253//*****************************************************************************
254QMyDialog::~QMyDialog()
255{
256 QMyConnectionItem* Item;
257 int i;
258
259 for (i = 0; i < 10; i++)
260 {
261 Item = ConnectionList[i];
262 delete Item;
263 }
264}
265
266//*****************************************************************************
267void QMyDialog::ComboChanged(int index)
268{
269 if (index == 0)
270 {
271 WidthEdit->setText("240");
272 HeightEdit->setText("320");
273 }
274 if (index == 1)
275 {
276 WidthEdit->setText("640");
277 HeightEdit->setText("480");
278 }
279 else if (index == 2)
280 {
281 WidthEdit->setText("800");
282 HeightEdit->setText("600");
283 }
284}
285
286//*****************************************************************************
287void QMyDialog::OKClicked()
288{
289 ServerName = ServerNameEdit->text();
290 UserName = UserNameEdit->text();
291 Width = WidthEdit->text().toInt();
292 Height = HeightEdit->text().toInt();
293 ServerIP = IPEdit->text();
294 FullScreen = FullScreenCheckBox->isChecked();
295 done(1);
296}
297
298//*****************************************************************************
299void QMyDialog::CancelClicked()
300{
301 done(0);
302}
303
304//*****************************************************************************
305void QMyDialog::AddClicked()
306{
307 int i;
308 QMyConnectionItem* Item;
309
310 i = ListBox->count();
311 if (i < 10)
312 {
313 ListBox->insertItem(ServerNameEdit->text());
314 Item = ConnectionList[i];
315 Item->ServerName = ServerNameEdit->text();
316 Item->UserName = UserNameEdit->text();
317 Item->Width = WidthEdit->text().toInt();
318 Item->Height = HeightEdit->text().toInt();
319 Item->ServerIP = IPEdit->text();
320 Item->FullScreen = FullScreenCheckBox->isChecked();
321 }
322}
323
324//*****************************************************************************
325void QMyDialog::EditClicked()
326{
327 int i;
328 QMyConnectionItem* Item;
329
330 i = ListBox->currentItem();
331 if (i >= 0)
332 {
333 Item = ConnectionList[i];
334 Item->ServerName = ServerNameEdit->text();
335 Item->UserName = UserNameEdit->text();
336 Item->Width = WidthEdit->text().toInt();
337 Item->Height = HeightEdit->text().toInt();
338 Item->ServerIP = IPEdit->text();
339 Item->FullScreen = FullScreenCheckBox->isChecked();
340 ListBox->changeItem(ServerNameEdit->text(), i);
341 }
342}
343
344//*****************************************************************************
345void WriteString(QFile* File, QString* Line)
346{
347 File->writeBlock((const char*)(*Line), Line->length());
348}
349
350//*****************************************************************************
351void QMyDialog::SaveClicked()
352{
353 int i, j;
354 QMyConnectionItem* Item;
355 QString Line;
356 char* home;
357 char Text[256];
358 QFile* File;
359
360 home = getenv("HOME");
361 if (home != NULL)
362 {
363 sprintf(Text, "%s/rdesktop.ini", home);
364 File = new QFile(Text);
365 if (File->open(IO_Truncate | IO_ReadWrite))
366 {
367 i = ListBox->count();
368 for (j = 0; j < i; j++)
369 {
370 Item = ConnectionList[j];
371 Line = "Server=";
372 Line += Item->ServerName;
373 Line += (char)10;
374 WriteString(File, &Line);
375 Line = "UserName=";
376 Line += Item->UserName;
377 Line += (char)10;
378 WriteString(File, &Line);
379 Line = "Width=";
380 sprintf(Text, "%d", Item->Width);
381 Line += Text;
382 Line += (char)10;
383 WriteString(File, &Line);
384 Line = "Height=";
385 sprintf(Text, "%d", Item->Height);
386 Line += Text;
387 Line += (char)10;
388 WriteString(File, &Line);
389 Line = "IP=";
390 Line += Item->ServerIP;
391 Line += (char)10;
392 WriteString(File, &Line);
393 Line = "FullScreen=";
394 if (Item->FullScreen)
395 Line += "1";
396 else
397 Line += "0";
398 Line += (char)10;
399 WriteString(File, &Line);
400 }
401 }
402 File->flush();
403 File->close();
404 delete File;
405 }
406}
407
408//*****************************************************************************
409void QMyDialog::RemoveClicked()
410{
411 int i, j, c;
412 QMyConnectionItem* Item1;
413 QMyConnectionItem* Item2;
414
415 i = ListBox->currentItem();
416 if (i >= 0)
417 {
418 c = ListBox->count();
419 for (j = i; j < c - 1; j++)
420 {
421 Item1 = ConnectionList[i];
422 Item2 = ConnectionList[i + 1];
423 Item1->ServerName = Item2->ServerName;
424 Item1->UserName = Item2->UserName;
425 Item1->Width = Item2->Width;
426 Item1->Height = Item2->Height;
427 Item1->ServerIP = Item2->ServerIP;
428 Item1->FullScreen = Item2->FullScreen;
429 }
430 ListBox->removeItem(i);
431 }
432}
433
434//*****************************************************************************
435void QMyDialog::ListBoxChanged()
436{
437 int i;
438 QMyConnectionItem* Item;
439 char Text[100];
440
441 i = ListBox->currentItem();
442 if (i >= 0 && i < 10)
443 {
444 Item = ConnectionList[i];
445 ServerNameEdit->setText(Item->ServerName);
446 UserNameEdit->setText(Item->UserName);
447 sprintf(Text, "%d", Item->Width);
448 WidthEdit->setText(Text);
449 sprintf(Text, "%d", Item->Height);
450 HeightEdit->setText(Text);
451 IPEdit->setText(Item->ServerIP);
452 FullScreenCheckBox->setChecked(Item->FullScreen != 0);
453 }
454}
455
456//*****************************************************************************
457void QMyDialog::ListBoxSelected(int /*index*/)
458{
459}
460
461//*****************************************************************************
462void GetScanCode(QKeyEvent* e, int* ScanCode, int* code)
463{
464 int key;
465 int mod;
466 int ascii;
467
468 key = e->key();
469 mod = e->state();
470 ascii = e->ascii();
471
472 *ScanCode = 0;
473 *code = mod; // 8 shift, 16 control, 32 alt
474
475 switch (key)
476 {
477 case 4096: // esc
478 case 4097: // tab
479 case 4099: // backspace
480 case 4100: // enter
481 case 4101: // enter
482 case 4103: // delete
483 ascii = 0;
484 }
485
486 if (ascii == 0)
487 {
488 switch (key)
489 {
490 case 4096: *ScanCode = 0x01; break; // esc
491 case 4097: *ScanCode = 0x0f; break; // tab
492 case 4099: *ScanCode = 0x0e; break; // backspace
493 case 4100: *ScanCode = 0x1c; break; // enter
494 case 4101: *ScanCode = 0x1c; break; // enter
495 case 4112: *ScanCode = 0xc7; break; // home
496 case 4113: *ScanCode = 0xcf; break; // end
497 case 4102: *ScanCode = 0xd2; break; // insert
498 case 4103: *ScanCode = 0xd3; break; // delete
499 case 4118: *ScanCode = 0xc9; break; // page up
500 case 4119: *ScanCode = 0xd1; break; // page down
501 case 4117: *ScanCode = 0xd0; break; // down arrow
502 case 4115: *ScanCode = 0xc8; break; // up arrow
503 case 4114: *ScanCode = 0xcb; break; // left arrow
504 case 4116: *ScanCode = 0xcd; break; // right arrow
505 case 4128: *ScanCode = 0x2a; break; // shift
506 case 4131: *ScanCode = 0x38; break; // alt
507 case 4129: *ScanCode = 0x1d; break; // ctrl
508 }
509 if (*ScanCode != 0)
510 return;
511 }
512
513 switch (ascii)
514 {
515 // first row
516 case 'q': *ScanCode = 0x10; break;
517 case 'Q': *ScanCode = 0x10; *code |= 8; break;
518 case '1': *ScanCode = 0x02; break;
519 case 'w': *ScanCode = 0x11; break;
520 case 'W': *ScanCode = 0x11; *code |= 8; break;
521 case '2': *ScanCode = 0x03; break;
522 case 'e': *ScanCode = 0x12; break;
523 case 'E': *ScanCode = 0x12; *code |= 8; break;
524 case '3': *ScanCode = 0x04; break;
525 case 'r': *ScanCode = 0x13; break;
526 case 'R': *ScanCode = 0x13; *code |= 8; break;
527 case '4': *ScanCode = 0x05; break;
528 case 't': *ScanCode = 0x14; break;
529 case 'T': *ScanCode = 0x14; *code |= 8; break;
530 case '5': *ScanCode = 0x06; break;
531 case 'y': *ScanCode = 0x15; break;
532 case 'Y': *ScanCode = 0x15; *code |= 8; break;
533 case '6': *ScanCode = 0x07; break;
534 case 'u': *ScanCode = 0x16; break;
535 case 'U': *ScanCode = 0x16; *code |= 8; break;
536 case '7': *ScanCode = 0x08; break;
537 case 'i': *ScanCode = 0x17; break;
538 case 'I': *ScanCode = 0x17; *code |= 8; break;
539 case '8': *ScanCode = 0x09; break;
540 case 'o': *ScanCode = 0x18; break;
541 case 'O': *ScanCode = 0x18; *code |= 8; break;
542 case '9': *ScanCode = 0x0a; break;
543 case 'p': *ScanCode = 0x19; break;
544 case 'P': *ScanCode = 0x19; *code |= 8; break;
545 case '0': *ScanCode = 0x0b; break;
546 // second row
547 case 'a': *ScanCode = 0x1e; break;
548 case 'A': *ScanCode = 0x1e; *code |= 8; break;
549 case '!': *ScanCode = 0x02; *code |= 8; break;
550 case 's': *ScanCode = 0x1f; break;
551 case 'S': *ScanCode = 0x1f; *code |= 8; break;
552 case '@': *ScanCode = 0x03; *code |= 8; break;
553 case 'd': *ScanCode = 0x20; break;
554 case 'D': *ScanCode = 0x20; *code |= 8; break;
555 case '#': *ScanCode = 0x04; *code |= 8; break;
556 case 'f': *ScanCode = 0x21; break;
557 case 'F': *ScanCode = 0x21; *code |= 8; break;
558 case '$': *ScanCode = 0x05; *code |= 8; break;
559 case 'g': *ScanCode = 0x22; break;
560 case 'G': *ScanCode = 0x22; *code |= 8; break;
561 case '%': *ScanCode = 0x06; *code |= 8; break;
562 case 'h': *ScanCode = 0x23; break;
563 case 'H': *ScanCode = 0x23; *code |= 8; break;
564 case '_': *ScanCode = 0x0c; *code |= 8; break;
565 case 'j': *ScanCode = 0x24; break;
566 case 'J': *ScanCode = 0x24; *code |= 8; break;
567 case '&': *ScanCode = 0x08; *code |= 8; break;
568 case 'k': *ScanCode = 0x25; break;
569 case 'K': *ScanCode = 0x25; *code |= 8; break;
570 case '*': *ScanCode = 0x09; *code |= 8; break;
571 case 'l': *ScanCode = 0x26; break;
572 case 'L': *ScanCode = 0x26; *code |= 8; break;
573 case '(': *ScanCode = 0x0a; *code |= 8; break;
574// case 8: *ScanCode = 0x0e; break; // backspace
575 // third row
576 case 'z': *ScanCode = 0x2c; break;
577 case 'Z': *ScanCode = 0x2c; *code |= 8; break;
578 case 'x': *ScanCode = 0x2d; break;
579 case 'X': *ScanCode = 0x2d; *code |= 8; break;
580 case 'c': *ScanCode = 0x2e; break;
581 case 'C': *ScanCode = 0x2e; *code |= 8; break;
582 case 'v': *ScanCode = 0x2f; break;
583 case 'V': *ScanCode = 0x2f; *code |= 8; break;
584 case 'b': *ScanCode = 0x30; break;
585 case 'B': *ScanCode = 0x30; *code |= 8; break;
586 case '-': *ScanCode = 0x0c; break;
587 case 'n': *ScanCode = 0x31; break;
588 case 'N': *ScanCode = 0x31; *code |= 8; break;
589 case '+': *ScanCode = 0x0d; *code |= 8; break;
590 case 'm': *ScanCode = 0x32; break;
591 case 'M': *ScanCode = 0x32; *code |= 8; break;
592 case '=': *ScanCode = 0x0d; break;
593 case ',': *ScanCode = 0x33; break;
594 case ';': *ScanCode = 0x27; break;
595 case ')': *ScanCode = 0x0b; *code |= 8; break;
596 // fourth row
597// case 9: *ScanCode = 0x0f; break; // tab
598 case '/': *ScanCode = 0x35; break;
599 case '?': *ScanCode = 0x35; *code |= 8; break;
600 case ' ': *ScanCode = 0x39; break;
601 case '\'': *ScanCode = 0x28; break;
602 case '"': *ScanCode = 0x28; *code |= 8; break;
603 case '~': *ScanCode = 0x29; *code |= 8; break;
604 case '.': *ScanCode = 0x34; break;
605 case ':': *ScanCode = 0x27; *code |= 8; break;
606 case '<': *ScanCode = 0x33; *code |= 8; break;
607// case 13: *ScanCode = 0x1c; break; // enter
608 case '>': *ScanCode = 0x34; *code |= 8; break;
609 // others
610// case 27: *ScanCode = 0x01; break; // esc
611 case '`': *ScanCode = 0x29; break;
612 case '^': *ScanCode = 0x07; *code |= 8; break;
613 case '[': *ScanCode = 0x1a; break;
614 case '{': *ScanCode = 0x1a; *code |= 8; break;
615 case ']': *ScanCode = 0x1b; break;
616 case '}': *ScanCode = 0x1b; *code |= 8; break;
617 case '\\': *ScanCode = 0x2b; break;
618 case '|': *ScanCode = 0x2b; *code |= 8; break;
619 // ctrl keys
620 case 1: *ScanCode = 0x1e; *code |= 16; break; // a
621 case 2: *ScanCode = 0x30; *code |= 16; break; // b
622 }
623
624 if (*ScanCode == 0 && key < 3000)
625 printf("unknown key %d mod %d ascii %d\n", key, mod, ascii);
626
627}
628
629//*****************************************************************************
630QMyScrollView::QMyScrollView() : QScrollView()
631{
632}
633
634//*****************************************************************************
635QMyScrollView::~QMyScrollView()
636{
637}
638
639//*****************************************************************************
640void QMyScrollView::keyPressEvent(QKeyEvent* e)
641{
642 int ScanCode, code;
643 GetScanCode(e, &ScanCode, &code);
644 if (ScanCode != 0)
645 {
646 if (code & 8) // send shift
647 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x2a, 0);
648 if (code & 16) // send control
649 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
650 if (code & 32) // send alt
651 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x38, 0);
652 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, ScanCode, 0);
653 e->accept();
654 }
655}
656
657//*****************************************************************************
658void QMyScrollView::keyReleaseEvent(QKeyEvent* e)
659{
660 int ScanCode, code;
661 GetScanCode(e, &ScanCode, &code);
662 if (ScanCode != 0)
663 {
664 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, ScanCode, 0);
665 if (code & 8) // send shift
666 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x2a, 0);
667 if (code & 16) // send control
668 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x1d, 0);
669 if (code & 32) // send alt
670 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x38, 0);
671 e->accept();
672 }
673}
674
675//*****************************************************************************
676void QMyScrollView::showEvent(QShowEvent* e)
677{
678 QScrollView::showEvent(e);
679}
680
681//*****************************************************************************
682void QMyScrollView::show()
683{
684 QScrollView::show();
685}
686
687//*****************************************************************************
688void QMyScrollView::polish()
689{
690 QScrollView::polish();
691}
692
693//*****************************************************************************
694void QMyScrollView::timerEvent(QTimerEvent* e)
695{
696 QScrollView::timerEvent(e);
697 killTimer(timer_id);
698 QMyDialog* d;
699 QWidget* Desktop;
700 int dw;
701 int dh;
702
703 d = new QMyDialog(this);
704 if (d->exec() == 1) // ok clicked
705 {
706 flags = RDP_LOGON_NORMAL;
707 g_width = d->Width;
708 g_height = d->Height;
709 fullscreen = d->FullScreen;
710 sprintf(server, "%s", (const char*)d->ServerIP);
711 sprintf(username, "%s", (const char*)d->UserName);
712 if (!rdp_connect(server, flags, domain, password, shell, directory))
713 {
714 delete d;
715 SV->close();
716 return;
717 }
718 BS = (uint8*)xmalloc(g_width * g_height);
719 memset(BS, 0, g_width * g_height);
720 clipx = 0;
721 clipy = 0;
722 clipcx = g_width;
723 clipcy = g_height;
724 CM = (QColorMap*)xmalloc(sizeof(struct QColorMap));
725 memset(CM, 0, sizeof(struct QColorMap));
726 CM->NumColors = 256;
727 MW = new QMyMainWindow();
728 MW->resize(g_width, g_height);
729 MW->show();
730 SV->addChild(MW);
731 MW->setMouseTracking(true);
732 SocketNotifier = new QSocketNotifier(global_sock, QSocketNotifier::Read, MW);
733 MW->connect(SocketNotifier, SIGNAL(activated(int)), MW, SLOT(dataReceived()));
734 if (fullscreen)
735 {
736 Desktop = App->desktop();
737 dw = Desktop->width();
738 dh = Desktop->height();
739 if (dw == g_width && dh == g_height)
740 MW->resize(g_width - 4, g_height - 4);
741 SV->showFullScreen();
742 }
743 delete d;
744 }
745 else // cancel clicked
746 {
747 delete d;
748 SV->close();
749 }
750}
751
752//*****************************************************************************
753QMyMainWindow::QMyMainWindow() : QWidget(SV->viewport())
754{
755 PopupMenu = new QPopupMenu(this);
756 PopupMenu->insertItem("Right click", 1, 0);
757 PopupMenu->insertItem("Toggle fullscreen", 2, 1);
758 PopupMenu->insertItem("Reset keyboard", 3, 2);
759 PopupMenu->insertItem("Double click", 4, 3);
760 connect(PopupMenu, SIGNAL(activated(int)), this, SLOT(MemuClicked(int)));
761}
762
763//*****************************************************************************
764QMyMainWindow::~QMyMainWindow()
765{
766 delete PopupMenu;
767}
768
769//*****************************************************************************
770void QMyMainWindow::timerEvent(QTimerEvent* e)
771{
772 QWidget::timerEvent(e);
773 if (e->timerId() == timer_id)
774 {
775 // send mouse up
776 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, mx, my);
777 // if in fullscreen, take it out or the menu won't work
778 if (fullscreen)
779 {
780 fullscreen = 0;
781 SV->showNormal();
782 SV->showMaximized();
783 }
784 else
785 PopupMenu->popup(mapToGlobal(QPoint(mx, my)));
786 }
787 killTimer(timer_id);
788}
789
790//*****************************************************************************
791void QMyMainWindow::MemuClicked(int MenuID)
792{
793 QWidget* Desktop;
794 int dw;
795 int dh;
796
797 if (MenuID == 1) // right click
798 {
799 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2, mx, my);
800 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, mx, my);
801 }
802 else if (MenuID == 2) // toggle full screen
803 {
804 fullscreen = ~fullscreen;
805 if (fullscreen)
806 {
807 Desktop = App->desktop();
808 dw = Desktop->width();
809 dh = Desktop->height();
810 if (dw == g_width && dh == g_height)
811 MW->resize(g_width - 4, g_height - 4);
812 SV->showFullScreen();
813 }
814 else
815 {
816 SV->showNormal();
817 SV->showMaximized();
818 MW->resize(g_width, g_height);
819 }
820 }
821 else if (MenuID == 3) // reset keyboard
822 {
823 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x2a, 0); // shift
824 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x1d, 0); // control
825 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x38, 0); // alt
826 }
827 else if (MenuID == 4) // double click
828 {
829 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1, mx, my);
830 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, mx, my);
831 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1, mx, my);
832 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, mx, my);
833 }
834}
835
836//*****************************************************************************
837void QMyMainWindow::mouseMoveEvent(QMouseEvent* e)
838{
839 int x;
840 int y;
841
842 x = e->x();
843 y = e->y();
844
845 if (timer_id)
846 {
847 x = x - mx;
848 y = y - my;
849 if (x < -10 || x > 10 || y < -10 || y > 10)
850 {
851 killTimer(timer_id);
852 timer_id = 0;
853 }
854 }
855 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, e->x(), e->y());
856}
857
858//*****************************************************************************
859void QMyMainWindow::mousePressEvent(QMouseEvent* e)
860{
861 timer_id = startTimer(1000);
862 mx = e->x();
863 my = e->y();
864 if (e->button() == LeftButton)
865 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1, e->x(), e->y());
866 else if (e->button() == RightButton)
867 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2, e->x(), e->y());
868 else if (e->button() == MidButton)
869 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON3, e->x(), e->y());
870}
871
872//*****************************************************************************
873void QMyMainWindow::mouseReleaseEvent(QMouseEvent* e)
874{
875 killTimer(timer_id);
876 timer_id = 0;
877 if (e->button() == LeftButton)
878 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, e->x(), e->y());
879 else if (e->button() == RightButton)
880 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, e->x(), e->y());
881 else if (e->button() == MidButton)
882 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, e->x(), e->y());
883}
884
885//*****************************************************************************
886void QMyMainWindow::wheelEvent(QWheelEvent* e)
887{
888 if (e->delta() > 0)
889 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON4, e->x(), e->y());
890 else if (e->delta() < 0)
891 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON5, e->x(), e->y());
892}
893
894#define NOT(x) (255-(x))
895
896//*****************************************************************************
897uint8 rop(int rop, uint8 src, uint8 dst)
898{
899 switch (rop)
900 {
901 case 0x0: return 0;
902 case 0x1: return NOT (src | dst);
903 case 0x2: return NOT (src) & dst;
904 case 0x3: return NOT (src);
905 case 0x4: return src & NOT (dst);
906 case 0x5: return NOT (dst);
907 case 0x6: return src ^ dst;
908 case 0x7: return NOT (src & dst);
909 case 0x8: return src & dst;
910 case 0x9: return NOT (src) ^ dst;
911 case 0xa: return dst;
912 case 0xb: return NOT (src) | dst;
913 case 0xc: return src;
914 case 0xd: return src | NOT (dst);
915 case 0xe: return src | dst;
916 case 0xf: return NOT (0);
917 }
918 return dst;
919}
920
921//*****************************************************************************
922uint8 get_pixel(int x, int y)
923{
924 if (x >= 0 && x < g_width && y >= 0 && y < g_height)
925 return BS[y * g_width + x];
926 else
927 return 0;
928}
929
930//*****************************************************************************
931void set_pixel(int x, int y, uint8 pixel, int op = 0xc)
932{
933 if (x >= clipx && x < (clipx + clipcx) && y >= clipy && y < (clipy + clipcy))
934 if (x >= 0 && x < g_width && y >= 0 && y < g_height)
935 if (op == 0xc)
936 BS[y * g_width + x] = pixel;
937 else
938 BS[y * g_width + x] = rop(op, pixel, BS[y * g_width + x]);
939}
940
941//******************************************************************************
942// adjust coordinates for cliping rect
943bool WarpCoords(int* x, int* y, int* cx, int* cy, int* srcx, int* srcy)
944{
945 int dx, dy;
946 QRect InRect(*x, *y, *cx, *cy);
947 QRect OutRect;
948 QRect CRect(clipx, clipy, clipcx, clipcy);
949 OutRect = InRect.intersect(CRect);
950 if (OutRect.isEmpty())
951 return false;
952 dx = OutRect.x() - InRect.x();
953 dy = OutRect.y() - InRect.y();
954 *x = OutRect.x();
955 *y = OutRect.y();
956 *cx = OutRect.width();
957 *cy = OutRect.height();
958 if (srcx != NULL)
959 *srcx = *srcx + dx;
960 if (srcy != NULL)
961 *srcy = *srcy + dy;
962 return true;
963}
964
965//*****************************************************************************
966void QMyMainWindow::paintEvent(QPaintEvent* pe)
967{
968 QImage* Image;
969 QPainter* Painter;
970 QRect Rect;
971 int i, j, w, h, l, t;
972 uint8* data;
973
974 if (!testWFlags(WRepaintNoErase))
975 setWFlags(WRepaintNoErase);
976 if (CM != NULL)
977 {
978 Rect = pe->rect();
979 l = Rect.left();
980 t = Rect.top();
981 w = Rect.width();
982 h = Rect.height();
983 if (w > 0 && h > 0 && CM->NumColors > 0)
984 {
985 data = (uint8*)xmalloc(w * h);
986 for (i = 0; i < h; i++)
987 for (j = 0; j < w; j++)
988 data[i * w + j] = get_pixel(l + j, t + i);
989 Image = new QImage(data, w, h, 8,(QRgb*)CM->RGBColors, CM->NumColors, QImage::IgnoreEndian);
990 Painter = new QPainter(this);
991 Painter->drawImage(l, t, *Image, 0, 0, w, h);
992 xfree(data);
993 delete Painter;
994 delete Image;
995 }
996 }
997}
998
999//*****************************************************************************
1000void QMyMainWindow::closeEvent(QCloseEvent* e)
1001{
1002 e->accept();
1003}
1004
1005//*****************************************************************************
1006void QMyMainWindow::dataReceived()
1007{
1008 if (rdp_main_loop())
1009 return;
1010 else
1011 SV->close();
1012}
1013
1014//*****************************************************************************
1015void redraw(int x, int y, int cx, int cy)
1016{
1017 if (WarpCoords(&x, &y, &cx, &cy, NULL, NULL))
1018 {
1019 MW->update(x, y, cx, cy);
1020 }
1021}
1022
1023/*
1024BOOL ui_init(void)
1025{
1026 QWidget* d;
1027
1028 CM = NULL;
1029 BS = NULL;
1030#ifdef SHARP
1031 App = new QPEApplication(g_argc, g_argv);
1032#else
1033 App = new QApplication(g_argc, g_argv, QApplication::GuiServer);
1034#endif
1035 if (fullscreen)
1036 {
1037 d = QApplication::desktop();
1038 width = d->width(); // returns screen width
1039 height = d->height(); // returns screen height
1040 }
1041 return True;
1042}
1043*/
1044
1045/*
1046void ui_deinit(void)
1047{
1048 delete App;
1049}
1050*/
1051
1052/*
1053BOOL ui_create_window(void)
1054{
1055 MW = new QMyMainWindow();
1056 MW->resize(width, height);
1057 SV = new QMyScrollView();
1058 SV->resize(width + 4, height + 4);
1059 App->setMainWidget(SV);
1060 SV->addChild(MW);
1061 MW->setMouseTracking(true);
1062 SocketNotifier = new QSocketNotifier(global_sock, QSocketNotifier::Read, MW);
1063 MW->connect(SocketNotifier, SIGNAL(activated(int)), MW, SLOT(dataReceived()));
1064 if (fullscreen)
1065 SV->showFullScreen();
1066 else
1067 SV->showMaximized();
1068 BS = (uint8*)xmalloc(width * height);
1069 memset(BS, 0, width * height);
1070 clipx = 0;
1071 clipy = 0;
1072 clipcx = width;
1073 clipcy = height;
1074 CM = (QColorMap*)xmalloc(sizeof(struct QColorMap));
1075 memset(CM, 0, sizeof(struct QColorMap));
1076 SV->timer_id = SV->startTimer(1000);
1077 return True;
1078}
1079*/
1080
1081/*
1082void ui_destroy_window(void)
1083{
1084 delete MW;
1085 delete SV;
1086 xfree(BS);
1087 xfree(CM);
1088}
1089*/
1090
1091//*****************************************************************************
1092/* Returns 0 after user quit, 1 otherwise */
1093int ui_select(int rdp_socket)
1094{
1095 global_sock = rdp_socket;
1096 return 1;
1097}
1098
1099//*****************************************************************************
1100void ui_move_pointer(int /*x*/, int /*y*/)
1101{
1102}
1103
1104//*****************************************************************************
1105HBITMAP ui_create_bitmap(int width, int height, uint8 * data)
1106{
1107 struct bitmap* the_bitmap;
1108 uint8* bitmap_data;
1109 int i, j;
1110
1111// printf("width %d height %d times %d\n", width, height, width * height);
1112 bitmap_data = (uint8*)xmalloc(width * height);
1113 the_bitmap = (struct bitmap*)xmalloc(sizeof(struct bitmap));
1114 the_bitmap->w = width;
1115 the_bitmap->h = height;
1116 the_bitmap->data = bitmap_data;
1117 for (i = 0; i < height; i++)
1118 for (j = 0; j < width; j++)
1119 bitmap_data[i * width + j] = data[i * width + j];
1120 return the_bitmap;
1121}
1122
1123//*****************************************************************************
1124void ui_paint_bitmap(int x, int y, int cx, int cy, int width,
1125 int height, uint8 * data)
1126{
1127 int i, j;
1128
1129 for (i = 0; i < cy; i++)
1130 for (j = 0; j < cx; j++)
1131 if (i < height)
1132 if (j < width)
1133 set_pixel(x + j, y + i, data[i * width + j]);
1134 redraw(x, y, cx, cy);
1135}
1136
1137//*****************************************************************************
1138void ui_destroy_bitmap(HBITMAP bmp)
1139{
1140 struct bitmap* the_bitmap;
1141
1142 the_bitmap = (struct bitmap*)bmp;
1143 if (the_bitmap != NULL)
1144 {
1145 if (the_bitmap->data != NULL)
1146 xfree(the_bitmap->data);
1147 xfree(the_bitmap);
1148 }
1149}
1150
1151//*****************************************************************************
1152bool is_pixel_on(uint8* data, int x, int y, int width, int bpp)
1153{
1154 int start, shift;
1155
1156 if (bpp == 1)
1157 {
1158 width = (width + 7) / 8;
1159 start = (y * width) + x / 8;
1160 shift = x % 8;
1161 return (data[start] & (0x80 >> shift)) != 0;
1162 }
1163 else if (bpp == 8)
1164 return data[y * width + x] != 0;
1165 else
1166 return false;
1167}
1168
1169//*****************************************************************************
1170void set_pixel_on(uint8* data, int x, int y, int width, int bpp, uint8 pixel)
1171{
1172 if (bpp == 8)
1173 data[y * width + x] = pixel;
1174}
1175
1176//*****************************************************************************
1177HGLYPH ui_create_glyph(int width, int height, uint8 * data)
1178{
1179 int i, j;
1180 uint8* glyph_data;
1181 struct bitmap* the_glyph;
1182
1183 glyph_data = (uint8*)xmalloc(width * height);
1184 the_glyph = (struct bitmap*)xmalloc(sizeof(struct bitmap));
1185 the_glyph->w = width;
1186 the_glyph->h = height;
1187 the_glyph->data = glyph_data;
1188 memset(glyph_data, 0, width * height);
1189 for (i = 0; i < height; i++)
1190 for (j = 0; j < width; j++)
1191 if (is_pixel_on(data, j, i, width, 1))
1192 set_pixel_on(glyph_data, j, i, width, 8, 255);
1193 return the_glyph;
1194}
1195
1196//*****************************************************************************
1197void ui_destroy_glyph(HGLYPH glyph)
1198{
1199 struct bitmap* the_glyph;
1200
1201 the_glyph = (struct bitmap*)glyph;
1202 if (the_glyph != NULL)
1203 {
1204 if (the_glyph->data != NULL)
1205 xfree(the_glyph->data);
1206 xfree(the_glyph);
1207 }
1208}
1209
1210//*****************************************************************************
1211HCURSOR ui_create_cursor(unsigned int /*x*/, unsigned int /*y*/,
1212 int /*width*/, int /*height*/, uint8 * /*andmask*/,
1213 uint8 * /*xormask*/)
1214{
1215 return (void*)1;
1216}
1217
1218//*****************************************************************************
1219void ui_set_cursor(HCURSOR /*cursor*/)
1220{
1221}
1222
1223//*****************************************************************************
1224void ui_destroy_cursor(HCURSOR /*cursor*/)
1225{
1226}
1227
1228//*****************************************************************************
1229HCOLOURMAP ui_create_colourmap(COLOURMAP * colours)
1230{
1231 int i;
1232 int x;
1233 uint8 r, g, b;
1234 i = 0;
1235 while (i < colours->ncolours && i < 256)
1236 {
1237 r = colours->colours[i].red;
1238 g = colours->colours[i].green;
1239 b = colours->colours[i].blue;
1240 x = (r << 16) | (g << 8) | b;
1241 CM->RGBColors[i] = x;
1242 i++;
1243 }
1244 CM->NumColors = colours->ncolours;
1245 return CM;
1246}
1247
1248//*****************************************************************************
1249void ui_destroy_colourmap(HCOLOURMAP /*map*/)
1250{
1251}
1252
1253//*****************************************************************************
1254void ui_set_colourmap(HCOLOURMAP /*map*/)
1255{
1256}
1257
1258//*****************************************************************************
1259void ui_begin_update(void)
1260{
1261}
1262
1263//*****************************************************************************
1264void ui_end_update(void)
1265{
1266}
1267
1268//*****************************************************************************
1269void ui_set_clip(int x, int y, int cx, int cy)
1270{
1271 clipx = x;
1272 clipy = y;
1273 clipcx = cx;
1274 clipcy = cy;
1275}
1276
1277//*****************************************************************************
1278void ui_reset_clip(void)
1279{
1280 clipx = 0;
1281 clipy = 0;
1282 clipcx = g_width;
1283 clipcy = g_height;
1284}
1285
1286//*****************************************************************************
1287void ui_bell(void)
1288{
1289 App->beep();
1290}
1291
1292//*****************************************************************************
1293void ui_destblt(uint8 opcode, int x, int y, int cx, int cy)
1294{
1295 int i, j;
1296
1297 for (i = 0; i < cy; i++)
1298 for (j = 0; j < cx; j++)
1299 set_pixel(x + j, y + i, get_pixel(x + j, y + i), opcode);
1300 redraw(x, y, cx, cy);
1301}
1302
1303//*****************************************************************************
1304// does not repaint
1305void fill_rect(int x, int y, int cx, int cy, int colour, int opcode = 0xc)
1306{
1307 int i, j;
1308
1309 for (i = 0; i < cy; i++)
1310 for (j = 0; j < cx; j++)
1311 set_pixel(x + j, y + i, colour, opcode);
1312}
1313
1314//*****************************************************************************
1315void ui_rect(int x, int y, int cx, int cy, int colour)
1316{
1317 fill_rect(x, y, cx, cy, colour);
1318 redraw(x, y, cx, cy);
1319}
1320
1321//*****************************************************************************
1322void ui_patblt(uint8 opcode, int x, int y, int cx, int cy,
1323 BRUSH * brush, int bgcolour, int fgcolour)
1324{
1325 int i, j;
1326 uint8 ipattern[8];
1327
1328 switch (brush->style)
1329 {
1330 case 0:
1331 fill_rect(x, y, cx, cy, fgcolour, opcode);
1332 break;
1333 case 3:
1334 for (i = 0; i < 8; i++)
1335 ipattern[i] = ~brush->pattern[7 - i];
1336 for (i = 0; i < cy; i++)
1337 for (j = 0; j < cx; j++)
1338 if (is_pixel_on(ipattern, (x + j + brush->xorigin) % 8,
1339 (y + i + brush->yorigin) % 8, 8, 1))
1340 set_pixel(x + j, y + i, fgcolour, opcode);
1341 else
1342 set_pixel(x + j, y + i, bgcolour, opcode);
1343 break;
1344 }
1345 redraw(x, y, cx, cy);
1346}
1347
1348//*****************************************************************************
1349void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,
1350 int srcx, int srcy)
1351{
1352 int i, j;
1353 uint8* temp;
1354
1355 temp = (uint8*)xmalloc(cx * cy);
1356 for (i = 0; i < cy; i++)
1357 for (j = 0; j < cx; j++)
1358 temp[i * cx + j] = get_pixel(srcx + j, srcy + i);
1359 for (i = 0; i < cy; i++)
1360 for (j = 0; j < cx; j++)
1361 set_pixel(x + j, y + i, temp[i * cx + j], opcode);
1362 xfree(temp);
1363 redraw(x, y, cx, cy);
1364}
1365
1366//*****************************************************************************
1367void ui_memblt(uint8 opcode, int x, int y, int cx, int cy,
1368 HBITMAP src, int srcx, int srcy)
1369{
1370 int i, j;
1371 struct bitmap* the_bitmap;
1372
1373 the_bitmap = (struct bitmap*)src;
1374 if (the_bitmap == NULL)
1375 return;
1376 for (i = 0; i < cy; i++)
1377 for (j = 0; j < cx; j++)
1378 if ((i + srcy) < the_bitmap->h && (j + srcx) < the_bitmap->w)
1379 set_pixel(x + j, y + i, the_bitmap->data[(i + srcy) * the_bitmap->w + (j + srcx)], opcode);
1380 redraw(x, y, cx, cy);
1381}
1382
1383//*****************************************************************************
1384// not used
1385void ui_triblt(uint8 /*opcode*/, int /*x*/, int /*y*/, int /*cx*/, int /*cy*/,
1386 HBITMAP /*src*/, int /*srcx*/, int /*srcy*/, BRUSH * /*brush*/,
1387 int /*bgcolour*/, int /*fgcolour*/)
1388{
1389}
1390
1391//*****************************************************************************
1392// Bresenham's line drawing algorithm
1393void ui_line(uint8 opcode, int startx, int starty, int endx,
1394 int endy, PEN * pen)
1395{
1396 int dx, dy, incx, incy, dpr, dpru, p, left, top, right, bottom;
1397
1398 if (startx > endx)
1399 {
1400 dx = startx - endx;
1401 incx = -1;
1402 left = endx;
1403 right = startx;
1404 }
1405 else
1406 {
1407 dx = endx - startx;
1408 incx = 1;
1409 left = startx;
1410 right = endx;
1411 }
1412 if (starty > endy)
1413 {
1414 dy = starty - endy;
1415 incy = -1;
1416 top = endy;
1417 bottom = starty;
1418 }
1419 else
1420 {
1421 dy = endy - starty;
1422 incy = 1;
1423 top = starty;
1424 bottom = endy;
1425 }
1426 if (dx >= dy)
1427 {
1428 dpr = dy << 1;
1429 dpru = dpr - (dx << 1);
1430 p = dpr - dx;
1431 for (; dx >= 0; dx--)
1432 {
1433 set_pixel(startx, starty, pen->colour, opcode);
1434 if (p > 0)
1435 {
1436 startx += incx;
1437 starty += incy;
1438 p += dpru;
1439 }
1440 else
1441 {
1442 startx += incx;
1443 p += dpr;
1444 }
1445 }
1446 }
1447 else
1448 {
1449 dpr = dx << 1;
1450 dpru = dpr - (dy << 1);
1451 p = dpr - dy;
1452 for (; dy >= 0; dy--)
1453 {
1454 set_pixel(startx, starty, pen->colour, opcode);
1455 if (p > 0)
1456 {
1457 startx += incx;
1458 starty += incy;
1459 p += dpru;
1460 }
1461 else
1462 {
1463 starty += incy;
1464 p += dpr;
1465 }
1466 }
1467 }
1468 redraw(left, top, (right - left) + 1, (bottom - top) + 1);
1469}
1470
1471//*****************************************************************************
1472void draw_glyph (int x, int y, HGLYPH glyph, int fgcolour)
1473{
1474 struct bitmap* the_glyph;
1475 int i, j;
1476
1477 the_glyph = (struct bitmap*)glyph;
1478 if (the_glyph == NULL)
1479 return;
1480 for (i = 0; i < the_glyph->h; i++)
1481 for (j = 0; j < the_glyph->w; j++)
1482 if (is_pixel_on(the_glyph->data, j, i, the_glyph->w, 8))
1483 set_pixel(x + j, y + i, fgcolour);
1484}
1485
1486#define DO_GLYPH(ttext,idx) \
1487{\
1488 glyph = cache_get_font (font, ttext[idx]);\
1489 if (!(flags & TEXT2_IMPLICIT_X))\
1490 {\
1491 xyoffset = ttext[++idx];\
1492 if ((xyoffset & 0x80))\
1493 {\
1494 if (flags & TEXT2_VERTICAL) \
1495 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1496 else\
1497 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1498 idx += 2;\
1499 }\
1500 else\
1501 {\
1502 if (flags & TEXT2_VERTICAL) \
1503 y += xyoffset;\
1504 else\
1505 x += xyoffset;\
1506 }\
1507 }\
1508 if (glyph != NULL)\
1509 {\
1510 draw_glyph (x + glyph->offset, y + glyph->baseline, glyph->pixmap, fgcolour);\
1511 if (flags & TEXT2_IMPLICIT_X)\
1512 x += glyph->width;\
1513 }\
1514}
1515
1516//*****************************************************************************
1517void ui_draw_text(uint8 font, uint8 flags, int mixmode,
1518 int x, int y, int clipx, int clipy,
1519 int clipcx, int clipcy, int boxx,
1520 int boxy, int boxcx, int boxcy, int bgcolour,
1521 int fgcolour, uint8 * text, uint8 length)
1522{
1523 FONTGLYPH *glyph;
1524 int i, j, xyoffset;
1525 DATABLOB *entry;
1526
1527 if (boxcx > 1)
1528 fill_rect(boxx, boxy, boxcx, boxcy, bgcolour);
1529 else if (mixmode == MIX_OPAQUE)
1530 fill_rect(clipx, clipy, clipcx, clipcy, bgcolour);
1531
1532 /* Paint text, character by character */
1533 for (i = 0; i < length;)
1534 {
1535 switch (text[i])
1536 {
1537 case 0xff:
1538 if (i + 2 < length)
1539 cache_put_text(text[i + 1], text, text[i + 2]);
1540 else
1541 {
1542 error("this shouldn't be happening\n");
1543 exit(1);
1544 }
1545 /* this will move pointer from start to first character after FF command */
1546 length -= i + 3;
1547 text = &(text[i + 3]);
1548 i = 0;
1549 break;
1550
1551 case 0xfe:
1552 entry = cache_get_text(text[i + 1]);
1553 if (entry != NULL)
1554 {
1555 if ((((uint8 *) (entry->data))[1] == 0) && (!(flags & TEXT2_IMPLICIT_X)))
1556 {
1557 if (flags & TEXT2_VERTICAL)
1558 y += text[i + 2];
1559 else
1560 x += text[i + 2];
1561 }
1562 for (j = 0; j < entry->size; j++)
1563 DO_GLYPH(((uint8 *) (entry->data)), j);
1564 }
1565 if (i + 2 < length)
1566 i += 3;
1567 else
1568 i += 2;
1569 length -= i;
1570 /* this will move pointer from start to first character after FE command */
1571 text = &(text[i]);
1572 i = 0;
1573 break;
1574
1575 default:
1576 DO_GLYPH(text, i);
1577 i++;
1578 break;
1579 }
1580 }
1581 if (boxcx > 1)
1582 redraw(boxx, boxy, boxcx, boxcy);
1583 else
1584 redraw(clipx, clipy, clipcx, clipcy);
1585}
1586
1587//*****************************************************************************
1588void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1589{
1590 uint8* data;
1591 int i, j;
1592
1593 data = (uint8*)xmalloc(cx * cy);
1594 for (i = 0; i < cy; i++)
1595 for (j = 0; j < cx; j++)
1596 data[i * cx + j] = get_pixel(x + j, y + i);
1597 cache_put_desktop(offset, cx, cy, cx, 1, data);
1598 xfree(data);
1599}
1600
1601//*****************************************************************************
1602void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1603{
1604 uint8* data;
1605 int i, j;
1606
1607 data = cache_get_desktop(offset, cx, cy, 1);
1608 for (i = 0; i < cy; i++)
1609 for (j = 0; j < cx; j++)
1610 set_pixel(x + j, y + i, data[i * cx + j]);
1611 redraw(x, y, cx, cy);
1612}
1613
1614//*****************************************************************************
1615int main(int argc, char** argv)
1616{
1617 CM = NULL;
1618 BS = NULL;
1619#ifdef SHARP
1620 App = new QPEApplication(argc, argv);
1621#else
1622 App = new QApplication(argc, argv, QApplication::GuiServer);
1623#endif
1624 SV = new QMyScrollView();
1625 App->setMainWidget(SV);
1626 SV->showMaximized();
1627 SV->timer_id = SV->startTimer(1000);
1628 App->exec();
1629 delete SV;
1630 delete App;
1631 if (CM != NULL)
1632 xfree(CM);
1633 if (BS !=NULL)
1634 xfree(BS);
1635 return 0;
1636}
1637
1638/*
1639 MW = new QMyMainWindow();
1640 MW->resize(width, height);
1641 SV->resize(width + 4, height + 4);
1642 App->setMainWidget(SV);
1643 SV->addChild(MW);
1644 MW->setMouseTracking(true);
1645 SocketNotifier = new QSocketNotifier(global_sock, QSocketNotifier::Read, MW);
1646 MW->connect(SocketNotifier, SIGNAL(activated(int)), MW, SLOT(dataReceived()));
1647 if (fullscreen)
1648 SV->showFullScreen();
1649 else
1650 SV->showMaximized();
1651 BS = (uint8*)xmalloc(width * height);
1652 memset(BS, 0, width * height);
1653 clipx = 0;
1654 clipy = 0;
1655 clipcx = width;
1656 clipcy = height;
1657 CM = (QColorMap*)xmalloc(sizeof(struct QColorMap));
1658 memset(CM, 0, sizeof(struct QColorMap));
1659 SV->timer_id = SV->startTimer(1000);
1660 return True;
1661
1662
1663
1664
1665
1666int main(int argc, char ** argv)
1667{
1668 uint32 flags;
1669 int i, total_params;
1670 char server[64] = "192.168.0.164";
1671 char domain[16] = "";
1672 char password[16] = "";
1673 char shell[128] = "";
1674 char directory[32] = "";
1675 char* p;
1676 QString param, s1, s2, s3;
1677
1678 flags = RDP_LOGON_NORMAL;
1679
1680 g_argc = argc;
1681 g_argv = argv;
1682
1683 if (!ui_init())
1684 return 1;
1685
1686 total_params = App->argc();
1687
1688 for (i = 1; (i + 1) < total_params; i = i + 2)
1689 {
1690 s1 = App->argv()[i];
1691 s2 = App->argv()[i + 1];
1692 if (s1 == "-g")
1693 {
1694 width = strtol((const char*)s2, &p, 10);
1695 if (*p == 'x')
1696 height = strtol(p + 1, NULL, 10);
1697 }
1698 else if (s1 = "-u")
1699 strcpy(username, (const char*)s2);
1700 }
1701 if (i < total_params)
1702 strcpy(server, App->argv()[i]);
1703
1704// printf("server %s width %d height %d\n", server, width, height);
1705
1706 if (width == 0 || height == 0)
1707 {
1708 ui_deinit();
1709 return 1;
1710 }
1711
1712 if (!rdp_connect(server, flags, domain, password, shell, directory))
1713 {
1714 ui_deinit();
1715 return 1;
1716 }
1717 if (ui_create_window())
1718 {
1719 ui_main_loop();
1720 ui_destroy_window();
1721 }
1722 rdp_disconnect();
1723 ui_deinit();
1724}
1725*/
diff --git a/noncore/net/opierdesktop/qtwin.h b/noncore/net/opierdesktop/qtwin.h
new file mode 100644
index 0000000..38ad190
--- a/dev/null
+++ b/noncore/net/opierdesktop/qtwin.h
@@ -0,0 +1,105 @@
1
2#include <qwidget.h>
3#include <qscrollview.h>
4#include <qdialog.h>
5#include <qlistbox.h>
6#include <qlineedit.h>
7#include <qcombobox.h>
8#include <qlabel.h>
9#include <qcheckbox.h>
10#include <qpopupmenu.h>
11
12class QMyConnectionItem
13{
14 public:
15 QString ServerName;
16 QString UserName;
17 QString ServerIP;
18 int Width;
19 int Height;
20 int FullScreen;
21};
22
23class QMyDialog: public QDialog
24{
25 Q_OBJECT
26 public:
27 QMyDialog(QWidget*);
28 ~QMyDialog();
29 public:
30 QListBox* ListBox;
31 QPushButton* OKButton;
32 QPushButton* CancelButton;
33 QLabel* Label1;
34 QLineEdit* ServerNameEdit;
35 QLabel* Label2;
36 QLineEdit* UserNameEdit;
37 QLabel* Label3;
38 QLineEdit* IPEdit;
39 QLineEdit* WidthEdit;
40 QLineEdit* HeightEdit;
41 QComboBox* WidthHeightBox;
42 QPushButton* AddButton;
43 QPushButton* EditButton;
44 QPushButton* SaveButton;
45 QPushButton* RemoveButton;
46 QCheckBox* FullScreenCheckBox;
47 public slots:
48 void ComboChanged(int);
49 void OKClicked();
50 void CancelClicked();
51 void AddClicked();
52 void EditClicked();
53 void SaveClicked();
54 void RemoveClicked();
55 void ListBoxChanged();
56 void ListBoxSelected(int);
57 public:
58 QString ServerName;
59 QString UserName;
60 QString ServerIP;
61 int Width;
62 int Height;
63 int FullScreen;
64 QMyConnectionItem* ConnectionList[10];
65};
66
67class QMyScrollView: public QScrollView
68{
69 Q_OBJECT
70 public:
71 QMyScrollView();
72 ~QMyScrollView();
73 void keyPressEvent(QKeyEvent*);
74 void keyReleaseEvent(QKeyEvent*);
75 void showEvent(QShowEvent*);
76 void show();
77 void polish();
78 void timerEvent(QTimerEvent*);
79 public:
80 int timer_id;
81};
82
83class QMyMainWindow: public QWidget
84{
85 Q_OBJECT
86 public:
87 QMyMainWindow();
88 ~QMyMainWindow();
89 void paintEvent(QPaintEvent*);
90 void mouseMoveEvent(QMouseEvent*);
91 void mousePressEvent(QMouseEvent*);
92 void mouseReleaseEvent(QMouseEvent*);
93 void wheelEvent(QWheelEvent*);
94 void closeEvent(QCloseEvent*);
95 void timerEvent(QTimerEvent*);
96 public slots:
97 void dataReceived();
98 void MemuClicked(int);
99 public:
100 QPopupMenu* PopupMenu;
101 int timer_id;
102 int mx;
103 int my;
104};
105
diff --git a/noncore/net/opierdesktop/rdesktop.cpp b/noncore/net/opierdesktop/rdesktop.cpp
new file mode 100644
index 0000000..1a9a087
--- a/dev/null
+++ b/noncore/net/opierdesktop/rdesktop.cpp
@@ -0,0 +1,313 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Entrypoint and utility functions
4 Copyright (C) Matthew Chapman 1999-2003
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21 //#include <stdarg.h> /* va_list va_start va_end */
22 #include <unistd.h> /* read close getuid getgid getpid getppid gethostname */
23 #include <fcntl.h> /* open */
24 #include <pwd.h> /* getpwuid */
25 //#include <termios.h> /* tcgetattr tcsetattr */
26 #include <sys/stat.h> /* stat */
27 #include <sys/time.h> /* gettimeofday */
28 #include <sys/times.h> /* times */
29#include <errno.h>
30#include "rdesktop.h"
31
32#ifdef EGD_SOCKET
33 #include <sys/socket.h> /* socket connect */
34 #include <sys/un.h> /* sockaddr_un */
35#endif
36
37//#ifdef WITH_OPENSSL
38#include <openssl/md5.h>
39//#else
40//#include "crypto/md5.h"
41//#endif
42
43/*extern "C" */void ui_main_loop(void);
44
45int g_argc;
46char ** g_argv;
47
48char title[32] = "";
49char username[16] = "j";
50char hostname[16] = "sharp";
51char keymapname[16];
52 int keylayout = 0x409; /* Defaults to US keyboard layout */
53 int g_width = 800; /* If width or height are reset to zero, the geometry will
54 be fetched from _NET_WORKAREA */
55int g_height = 600;
56int tcp_port_rdp = TCP_PORT_RDP;
57int server_bpp = 8;
58 int win_button_size = 0;/* If zero, disable single app mode */
59BOOL bitmap_compression = True;
60BOOL sendmotion = True;
61BOOL orders = True;
62BOOL encryption = True;
63BOOL desktop_save = True;
64BOOL fullscreen = False;
65BOOL grab_keyboard = True;
66BOOL hide_decorations = False;
67extern BOOL owncolmap;
68
69/* report an unimplemented protocol feature */
70void
71unimpl(char *format, ...)
72{
73}
74
75/* malloc; exit if out of memory */
76void *
77xmalloc(int size)
78{
79 void *mem = malloc(size);
80 if (mem == NULL)
81 {
82 error("xmalloc %d\n", size);
83 exit(1);
84 }
85 return mem;
86}
87
88/* realloc; exit if out of memory */
89void *
90xrealloc(void *oldmem, int size)
91{
92 void *mem = realloc(oldmem, size);
93 if (mem == NULL)
94 {
95 error("xrealloc %d\n", size);
96 exit(1);
97 }
98 return mem;
99}
100
101/* free */
102void
103xfree(void *mem)
104{
105 free(mem);
106}
107
108/* report an error */
109void
110error(char *format, ...)
111{
112}
113
114/* report a warning */
115void
116warning(char *format, ...)
117{
118}
119
120/* Generate a 32-byte random for the secure transport code. */
121void
122generate_random(uint8 * random)
123{
124 struct stat st;
125 struct tms tmsbuf;
126 MD5_CTX md5;
127 uint32 *r;
128 int fd, n;
129
130 /* If we have a kernel random device, try that first */
131 if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
132 || ((fd = open("/dev/random", O_RDONLY)) != -1))
133 {
134 n = read(fd, random, 32);
135 close(fd);
136 if (n == 32)
137 return;
138 }
139 /* Otherwise use whatever entropy we can gather - ideas welcome. */
140 r = (uint32 *) random;
141 r[0] = (getpid()) | (getppid() << 16);
142 r[1] = (getuid()) | (getgid() << 16);
143 r[2] = times(&tmsbuf);/* system uptime (clocks) */
144 gettimeofday((struct timeval *) &r[3], NULL);/* sec and usec */
145 stat("/tmp", &st);
146 r[5] = st.st_atime;
147 r[6] = st.st_mtime;
148 r[7] = st.st_ctime;
149
150 /* Hash both halves with MD5 to obscure possible patterns */
151 MD5_Init(&md5);
152 MD5_Update(&md5, random, 16);
153 MD5_Final(random, &md5);
154 MD5_Update(&md5, random + 16, 16);
155 MD5_Final(random + 16, &md5);
156}
157
158int
159load_licence(unsigned char **data)
160{
161 char *path;
162 char *home;
163 struct stat st;
164 int fd;
165
166 home = getenv("HOME");
167 if (home == NULL)
168 return -1;
169
170 path = (char*)xmalloc(strlen(home) + strlen(hostname) + 20);
171 sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
172
173 fd = open(path, O_RDONLY);
174 if (fd == -1)
175 return -1;
176
177 if (fstat(fd, &st))
178 return -1;
179
180 *data = (unsigned char*)xmalloc(st.st_size);
181 return read(fd, *data, st.st_size);
182}
183
184void
185save_licence(unsigned char *data, int length)
186{
187 char *fpath; /* file path for licence */
188 char *fname, *fnamewrk;/* file name for licence .inkl path. */
189 char *home;
190 uint32 y;
191 struct flock fnfl;
192 int fnfd, fnwrkfd, i, wlen;
193 struct stream s, *s_ptr;
194 uint32 len;
195
196 /* Construct a stream, so that we can use macros to extract the
197 * licence.
198 */
199 s_ptr = &s;
200 s_ptr->p = data;
201 /* Skip first two bytes */
202 in_uint16(s_ptr, len);
203
204 /* Skip three strings */
205 for (i = 0; i < 3; i++)
206 {
207 in_uint32(s_ptr, len);
208 s_ptr->p += len;
209 /* Make sure that we won't be past the end of data after
210 * reading the next length value
211 */
212 if ((s_ptr->p) + 4 > data + length)
213 {
214 printf("Error in parsing licence key.\n");
215 printf("Strings %d end value %x > supplied length (%x)\n", i,
216 (unsigned int) s_ptr->p, (unsigned int) data + length);
217 return;
218 }
219 }
220 in_uint32(s_ptr, len);
221 if (s_ptr->p + len > data + length)
222 {
223 printf("Error in parsing licence key.\n");
224 printf("End of licence %x > supplied length (%x)\n",
225 (unsigned int) s_ptr->p + len, (unsigned int) data + length);
226 return;
227 }
228
229 home = getenv("HOME");
230 if (home == NULL)
231 return;
232
233 /* set and create the directory -- if it doesn't exist. */
234 fpath = (char*)xmalloc(strlen(home) + 11);
235 STRNCPY(fpath, home, strlen(home) + 1);
236
237 sprintf(fpath, "%s/.rdesktop", fpath);
238 if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
239 {
240 perror("mkdir");
241 exit(1);
242 }
243
244 /* set the real licence filename, and put a write lock on it. */
245 fname = (char*)xmalloc(strlen(fpath) + strlen(hostname) + 10);
246 sprintf(fname, "%s/licence.%s", fpath, hostname);
247 fnfd = open(fname, O_RDONLY);
248 if (fnfd != -1)
249 {
250 fnfl.l_type = F_WRLCK;
251 fnfl.l_whence = SEEK_SET;
252 fnfl.l_start = 0;
253 fnfl.l_len = 1;
254 fcntl(fnfd, F_SETLK, &fnfl);
255 }
256
257 /* create a temporary licence file */
258 fnamewrk = (char*)xmalloc(strlen(fname) + 12);
259 for (y = 0;; y++)
260 {
261 sprintf(fnamewrk, "%s.%lu", fname, (long unsigned int) y);
262 fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
263 if (fnwrkfd == -1)
264 {
265 if (errno == EINTR || errno == EEXIST)
266 continue;
267 perror("create");
268 exit(1);
269 }
270 break;
271 }
272 /* write to the licence file */
273 for (y = 0; y < len;)
274 {
275 do
276 {
277 wlen = write(fnwrkfd, s_ptr->p + y, len - y);
278 }
279 while (wlen == -1 && errno == EINTR);
280 if (wlen < 1)
281 {
282 perror("write");
283 unlink(fnamewrk);
284 exit(1);
285 }
286 y += wlen;
287 }
288
289 /* close the file and rename it to fname */
290 if (close(fnwrkfd) == -1)
291 {
292 perror("close");
293 unlink(fnamewrk);
294 exit(1);
295 }
296 if (rename(fnamewrk, fname) == -1)
297 {
298 perror("rename");
299 unlink(fnamewrk);
300 exit(1);
301 }
302 /* close the file lock on fname */
303 if (fnfd != -1)
304 {
305 fnfl.l_type = F_UNLCK;
306 fnfl.l_whence = SEEK_SET;
307 fnfl.l_start = 0;
308 fnfl.l_len = 1;
309 fcntl(fnfd, F_SETLK, &fnfl);
310 close(fnfd);
311 }
312
313}
diff --git a/noncore/net/opierdesktop/rdesktop.h b/noncore/net/opierdesktop/rdesktop.h
new file mode 100644
index 0000000..0fca123
--- a/dev/null
+++ b/noncore/net/opierdesktop/rdesktop.h
@@ -0,0 +1,66 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Master include file
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24
25//#define __LITTLE_ENDIAN 1234
26//#define __BIG_ENDIAN 4321
27//#define __BYTE_ORDER __BIG_ENDIAN
28
29//#if __BYTE_ORDER == __LITTLE_ENDIAN
30#define L_ENDIAN
31#define NEED_ALIGN
32//#error le
33//#elif __BYTE_ORDER == __BIG_ENDIAN
34//#define B_ENDIAN
35//#error be
36//#else
37//#error Unknown endianness. Edit rdesktop.h.
38//#endif
39
40
41//#define B_ENDIAN
42//#define B_ENDIAN_PREFERRED
43
44#define VERSION "1.2.0"
45
46#ifdef WITH_DEBUG
47 #define DEBUG(args)printf args;
48#else
49#define DEBUG(args)
50#endif
51
52#ifdef WITH_DEBUG_KBD
53#define DEBUG_KBD(args) printf args;
54#else
55#define DEBUG_KBD(args)
56#endif
57
58#define STRNCPY(dst,src,n) { strncpy(dst,src,n-1); dst[n-1] = 0; }
59
60#include "constants.h"
61#include "types.h"
62#include "parse.h"
63
64#ifndef MAKE_PROTO
65#include "proto.h"
66#endif
diff --git a/noncore/net/opierdesktop/rdp.cpp b/noncore/net/opierdesktop/rdp.cpp
new file mode 100644
index 0000000..bab8568
--- a/dev/null
+++ b/noncore/net/opierdesktop/rdp.cpp
@@ -0,0 +1,748 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "rdesktop.h"
22
23extern uint16 mcs_userid;
24extern char username[16];
25extern BOOL bitmap_compression;
26extern BOOL orders;
27extern BOOL encryption;
28extern BOOL desktop_save;
29
30uint8 *next_packet;
31uint32 rdp_shareid;
32
33/* Initialise an RDP packet */
34static STREAM
35rdp_init(int maxlen)
36{
37 STREAM s;
38
39 s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 6);
40 s_push_layer(s, rdp_hdr, 6);
41
42 return s;
43}
44
45/* Send an RDP packet */
46static void
47rdp_send(STREAM s, uint8 pdu_type)
48{
49 uint16 length;
50
51 s_pop_layer(s, rdp_hdr);
52 length = s->end - s->p;
53
54 out_uint16_le(s, length);
55 out_uint16_le(s, (pdu_type | 0x10));/* Version 1 */
56 out_uint16_le(s, (mcs_userid + 1001));
57
58 sec_send(s, encryption ? SEC_ENCRYPT : 0);
59}
60
61/* Receive an RDP packet */
62STREAM
63rdp_recv(uint8 * type)
64{
65 static STREAM rdp_s;
66 uint16 length, pdu_type;
67
68 if ((rdp_s == NULL) || (next_packet >= rdp_s->end))
69 {
70 rdp_s = sec_recv();
71 if (rdp_s == NULL)
72 return NULL;
73
74 next_packet = rdp_s->p;
75 }
76 else
77 {
78 rdp_s->p = next_packet;
79 }
80
81 in_uint16_le(rdp_s, length);
82 /* 32k packets are really 8, keepalive fix */
83 if (length == 0x8000)
84 {
85 next_packet += 8;
86 *type = 0;
87 return rdp_s;
88 }
89 in_uint16_le(rdp_s, pdu_type);
90 in_uint8s(rdp_s, 2);/* userid */
91 *type = pdu_type & 0xf;
92
93#if WITH_DEBUG
94 DEBUG(("RDP packet (type %x):\n", *type));
95 hexdump(next_packet, length);
96#endif /* */
97
98 next_packet += length;
99 return rdp_s;
100}
101
102/* Initialise an RDP data packet */
103static STREAM
104rdp_init_data(int maxlen)
105{
106 STREAM s;
107
108 s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 18);
109 s_push_layer(s, rdp_hdr, 18);
110
111 return s;
112}
113
114/* Send an RDP data packet */
115static void
116rdp_send_data(STREAM s, uint8 data_pdu_type)
117{
118 uint16 length;
119
120 s_pop_layer(s, rdp_hdr);
121 length = s->end - s->p;
122
123 out_uint16_le(s, length);
124 out_uint16_le(s, (RDP_PDU_DATA | 0x10));
125 out_uint16_le(s, (mcs_userid + 1001));
126
127 out_uint32_le(s, rdp_shareid);
128 out_uint8(s, 0);/* pad */
129 out_uint8(s, 1);/* streamid */
130 out_uint16_le(s, (length - 14));
131 out_uint8(s, data_pdu_type);
132 out_uint8(s, 0);/* compress_type */
133 out_uint16(s, 0);/* compress_len */
134
135 sec_send(s, encryption ? SEC_ENCRYPT : 0);
136}
137
138/* Output a string in Unicode */
139void
140rdp_out_unistr(STREAM s, char *string, int len)
141{
142 int i = 0, j = 0;
143
144 len += 2;
145
146 while (i < len)
147 {
148 s->p[i++] = string[j++];
149 s->p[i++] = 0;
150 }
151
152 s->p += len;
153}
154
155/* Parse a logon info packet */
156static void
157rdp_send_logon_info(uint32 flags, char *domain, char *user,
158 char *password, char *program, char *directory)
159{
160 int len_domain = 2 * strlen(domain);
161 int len_user = 2 * strlen(user);
162 int len_password = 2 * strlen(password);
163 int len_program = 2 * strlen(program);
164 int len_directory = 2 * strlen(directory);
165 uint32 sec_flags = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
166 STREAM s;
167
168 s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
169 + len_program + len_directory + 10);
170
171 out_uint32(s, 0);
172 out_uint32_le(s, flags);
173 out_uint16_le(s, len_domain);
174 out_uint16_le(s, len_user);
175 out_uint16_le(s, len_password);
176 out_uint16_le(s, len_program);
177 out_uint16_le(s, len_directory);
178 rdp_out_unistr(s, domain, len_domain);
179 rdp_out_unistr(s, user, len_user);
180 rdp_out_unistr(s, password, len_password);
181 rdp_out_unistr(s, program, len_program);
182 rdp_out_unistr(s, directory, len_directory);
183
184 s_mark_end(s);
185 sec_send(s, sec_flags);
186}
187
188/* Send a control PDU */
189static void
190rdp_send_control(uint16 action)
191{
192 STREAM s;
193
194 s = rdp_init_data(8);
195
196 out_uint16_le(s, action);
197 out_uint16(s, 0);/* userid */
198 out_uint32(s, 0);/* control id */
199
200 s_mark_end(s);
201 rdp_send_data(s, RDP_DATA_PDU_CONTROL);
202}
203
204/* Send a synchronisation PDU */
205static void
206rdp_send_synchronise(void)
207{
208 STREAM s;
209
210 s = rdp_init_data(4);
211
212 out_uint16_le(s, 1);/* type */
213 out_uint16_le(s, 1002);
214
215 s_mark_end(s);
216 rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
217}
218
219/* Send a single input event */
220void
221rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
222{
223 STREAM s;
224
225 s = rdp_init_data(16);
226
227 out_uint16_le(s, 1);/* number of events */
228 out_uint16(s, 0);/* pad */
229
230 out_uint32_le(s, time);
231 out_uint16_le(s, message_type);
232 out_uint16_le(s, device_flags);
233 out_uint16_le(s, param1);
234 out_uint16_le(s, param2);
235
236 s_mark_end(s);
237 rdp_send_data(s, RDP_DATA_PDU_INPUT);
238}
239
240/* Send an (empty) font information PDU */
241static void
242rdp_send_fonts(uint16 seq)
243{
244 STREAM s;
245
246 s = rdp_init_data(8);
247
248 out_uint16(s, 0);/* number of fonts */
249 out_uint16_le(s, 0x3e);/* unknown */
250 out_uint16_le(s, seq);/* unknown */
251 out_uint16_le(s, 0x32);/* entry size */
252
253 s_mark_end(s);
254 rdp_send_data(s, RDP_DATA_PDU_FONT2);
255}
256
257/* Output general capability set */
258static void
259rdp_out_general_caps(STREAM s)
260{
261 out_uint16_le(s, RDP_CAPSET_GENERAL);
262 out_uint16_le(s, RDP_CAPLEN_GENERAL);
263
264 out_uint16_le(s, 1);/* OS major type */
265 out_uint16_le(s, 3);/* OS minor type */
266 out_uint16_le(s, 0x200);/* Protocol version */
267 out_uint16(s, 0);/* Pad */
268 out_uint16(s, 0);/* Compression types */
269 out_uint16(s, 0);/* Pad */
270 out_uint16(s, 0);/* Update capability */
271 out_uint16(s, 0);/* Remote unshare capability */
272 out_uint16(s, 0);/* Compression level */
273 out_uint16(s, 0);/* Pad */
274}
275
276/* Output bitmap capability set */
277static void
278rdp_out_bitmap_caps(STREAM s)
279{
280 out_uint16_le(s, RDP_CAPSET_BITMAP);
281 out_uint16_le(s, RDP_CAPLEN_BITMAP);
282
283 out_uint16_le(s, 8);/* Preferred BPP */
284 out_uint16_le(s, 1);/* Receive 1 BPP */
285 out_uint16_le(s, 1);/* Receive 4 BPP */
286 out_uint16_le(s, 1);/* Receive 8 BPP */
287 out_uint16_le(s, 800);/* Desktop width */
288 out_uint16_le(s, 600);/* Desktop height */
289 out_uint16(s, 0);/* Pad */
290 out_uint16(s, 0);/* Allow resize */
291 out_uint16_le(s, bitmap_compression ? 1 : 0);/* Support compression */
292 out_uint16(s, 0);/* Unknown */
293 out_uint16_le(s, 1);/* Unknown */
294 out_uint16(s, 0);/* Pad */
295}
296
297/* Output order capability set */
298static void
299rdp_out_order_caps(STREAM s)
300{
301 uint8 order_caps[32];
302
303
304 memset(order_caps, 0, 32);
305 order_caps[0] = 1;/* dest blt */
306 order_caps[1] = 1;/* pat blt */
307 order_caps[2] = 1;/* screen blt */
308 // order_caps[3] = 1;/* required for memblt? */
309 order_caps[8] = 1;/* line */
310 order_caps[9] = 1;/* line */
311 order_caps[10] = 1;/* rect */
312 order_caps[11] = (desktop_save == False ? 0 : 1);/* desksave */
313 order_caps[13] = 1;/* memblt */
314 order_caps[14] = 1;/* triblt */
315 order_caps[22] = 1;/* polyline */
316 order_caps[27] = 1;/* text2 */
317 out_uint16_le(s, RDP_CAPSET_ORDER);
318 out_uint16_le(s, RDP_CAPLEN_ORDER);
319
320 out_uint8s(s, 20);/* Terminal desc, pad */
321 out_uint16_le(s, 1);/* Cache X granularity */
322 out_uint16_le(s, 20);/* Cache Y granularity */
323 out_uint16(s, 0);/* Pad */
324 out_uint16_le(s, 1);/* Max order level */
325 out_uint16_le(s, 0x147);/* Number of fonts */
326 out_uint16_le(s, 0x2a);/* Capability flags */
327 out_uint8p(s, order_caps, 32);/* Orders supported */
328 out_uint16_le(s, 0x6a1);/* Text capability flags */
329 out_uint8s(s, 6);/* Pad */
330 out_uint32_le(s, desktop_save == False ? 0 : 0x38400);/* Desktop cache size */
331 //out_uint32_le(s, 0); // desktop cache set to 0
332 out_uint32(s, 0);/* Unknown */
333 out_uint32_le(s, 0x4e4);/* Unknown */
334}
335
336/* Output bitmap cache capability set */
337static void
338rdp_out_bmpcache_caps(STREAM s)
339{
340 out_uint16_le(s, RDP_CAPSET_BMPCACHE);
341 out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
342
343 out_uint8s(s, 24);/* unused */
344 out_uint16_le(s, 0x258);/* entries */
345 out_uint16_le(s, 0x100);/* max cell size */
346 out_uint16_le(s, 0x12c);/* entries */
347 out_uint16_le(s, 0x400);/* max cell size */
348 out_uint16_le(s, 0x106);/* entries */
349 out_uint16_le(s, 0x1000);/* max cell size */
350}
351
352/* Output control capability set */
353static void
354rdp_out_control_caps(STREAM s)
355{
356 out_uint16_le(s, RDP_CAPSET_CONTROL);
357 out_uint16_le(s, RDP_CAPLEN_CONTROL);
358
359 out_uint16(s, 0);/* Control capabilities */
360 out_uint16(s, 0);/* Remote detach */
361 out_uint16_le(s, 2);/* Control interest */
362 out_uint16_le(s, 2);/* Detach interest */
363}
364
365/* Output activation capability set */
366static void
367rdp_out_activate_caps(STREAM s)
368{
369 out_uint16_le(s, RDP_CAPSET_ACTIVATE);
370 out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
371
372 out_uint16(s, 0);/* Help key */
373 out_uint16(s, 0);/* Help index key */
374 out_uint16(s, 0);/* Extended help key */
375 out_uint16(s, 0);/* Window activate */
376}
377
378/* Output pointer capability set */
379static void
380rdp_out_pointer_caps(STREAM s)
381{
382 out_uint16_le(s, RDP_CAPSET_POINTER);
383 out_uint16_le(s, RDP_CAPLEN_POINTER);
384
385 out_uint16(s, 0);/* Colour pointer */
386 out_uint16_le(s, 20);/* Cache size */
387}
388
389/* Output share capability set */
390static void
391rdp_out_share_caps(STREAM s)
392{
393 out_uint16_le(s, RDP_CAPSET_SHARE);
394 out_uint16_le(s, RDP_CAPLEN_SHARE);
395
396 out_uint16(s, 0);/* userid */
397 out_uint16(s, 0);/* pad */
398}
399
400/* Output colour cache capability set */
401static void
402rdp_out_colcache_caps(STREAM s)
403{
404 out_uint16_le(s, RDP_CAPSET_COLCACHE);
405 out_uint16_le(s, RDP_CAPLEN_COLCACHE);
406
407 out_uint16_le(s, 6);/* cache size */
408 out_uint16(s, 0);/* pad */
409}
410
411static uint8 canned_caps[] = {
412 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
418 0x00, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x0C, 0x00, 0x08, 0x00, 0x01,
423 0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
424 0x10, 0x00, 0x34, 0x00, 0xFE,
425 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
426 0xFE, 0x00, 0x08, 0x00, 0xFE,
427 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
428 0xFE, 0x00, 0x80, 0x00, 0xFE,
429 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
430 0x02, 0x00, 0x00, 0x00
431};
432
433/* Output unknown capability set */
434static void
435rdp_out_unknown_caps(STREAM s)
436{
437 out_uint16_le(s, RDP_CAPSET_UNKNOWN);
438 out_uint16_le(s, 0x58);
439
440 out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
441}
442
443/* Send a confirm active PDU */
444static void
445rdp_send_confirm_active(void)
446{
447 STREAM s;
448 uint16 caplen =
449 RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
450 RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
451 RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
452 RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
453
454 s = rdp_init(14 + caplen + sizeof(RDP_SOURCE));
455
456 out_uint32_le(s, rdp_shareid);
457 out_uint16_le(s, 0x3ea);/* userid */
458 out_uint16_le(s, sizeof(RDP_SOURCE));
459 out_uint16_le(s, caplen);
460
461 out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
462 out_uint16_le(s, 0xd);/* num_caps */
463 out_uint8s(s, 2);/* pad */
464
465 rdp_out_general_caps(s);
466 rdp_out_bitmap_caps(s);
467 rdp_out_order_caps(s);
468 rdp_out_bmpcache_caps(s);
469 rdp_out_colcache_caps(s);
470 rdp_out_activate_caps(s);
471 rdp_out_control_caps(s);
472 rdp_out_pointer_caps(s);
473 rdp_out_share_caps(s);
474 rdp_out_unknown_caps(s);
475
476 s_mark_end(s);
477 rdp_send(s, RDP_PDU_CONFIRM_ACTIVE);
478}
479
480/* Respond to a demand active PDU */
481void
482process_demand_active(STREAM s)
483{
484 uint8 type;
485
486 in_uint32_le(s, rdp_shareid);
487
488 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid));
489
490 rdp_send_confirm_active();
491 rdp_send_synchronise();
492 rdp_send_control(RDP_CTL_COOPERATE);
493 rdp_send_control(RDP_CTL_REQUEST_CONTROL);
494 rdp_recv(&type);/* RDP_PDU_SYNCHRONIZE */
495 rdp_recv(&type);/* RDP_CTL_COOPERATE */
496 rdp_recv(&type);/* RDP_CTL_GRANT_CONTROL */
497 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);
498 rdp_send_fonts(1);
499 rdp_send_fonts(2);
500 rdp_recv(&type);/* RDP_PDU_UNKNOWN 0x28 */
501 reset_order_state();
502}
503
504/* Process a pointer PDU */
505static void
506process_pointer_pdu(STREAM s)
507{
508 uint16 message_type;
509 uint16 x, y, width, height, cache_idx, masklen, datalen;
510 uint8 *mask, *data;
511 HCURSOR cursor;
512
513 in_uint16_le(s, message_type);
514 in_uint8s(s, 2);/* pad */
515
516 switch (message_type)
517 {
518 case RDP_POINTER_MOVE:
519 in_uint16_le(s, x);
520 in_uint16_le(s, y);
521 if (s_check(s))
522 ui_move_pointer(x, y);
523 break;
524
525 case RDP_POINTER_COLOR:
526 in_uint16_le(s, cache_idx);
527 in_uint16_le(s, x);
528 in_uint16_le(s, y);
529 in_uint16_le(s, width);
530 in_uint16_le(s, height);
531 in_uint16_le(s, masklen);
532 in_uint16_le(s, datalen);
533 in_uint8p(s, data, datalen);
534 in_uint8p(s, mask, masklen);
535 cursor = ui_create_cursor(x, y, width, height, mask, data);
536 ui_set_cursor(cursor);
537 cache_put_cursor(cache_idx, cursor);
538 break;
539
540 case RDP_POINTER_CACHED:
541 in_uint16_le(s, cache_idx);
542 ui_set_cursor(cache_get_cursor(cache_idx));
543 break;
544
545 default:
546 DEBUG(("Pointer message 0x%x\n", message_type));
547 }
548}
549
550/* Process bitmap updates */
551static void
552process_bitmap_updates(STREAM s)
553{
554 uint16 num_updates;
555 uint16 left, top, right, bottom, width, height;
556 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
557 uint8 *data, *bmpdata;
558 int i;
559
560 in_uint16_le(s, num_updates);
561
562 for (i = 0; i < num_updates; i++)
563 {
564 in_uint16_le(s, left);
565 in_uint16_le(s, top);
566 in_uint16_le(s, right);
567 in_uint16_le(s, bottom);
568 in_uint16_le(s, width);
569 in_uint16_le(s, height);
570 in_uint16_le(s, bpp);
571 Bpp = (bpp + 7) / 8;
572 in_uint16_le(s, compress);
573 in_uint16_le(s, bufsize);
574
575 cx = right - left + 1;
576 cy = bottom - top + 1;
577
578 DEBUG(("UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,cmp=%d)\n",
579 left, top, right, bottom, width, height, compress));
580
581 if (!compress)
582 {
583 int y;
584 bmpdata = (uint8*)xmalloc(width * height * Bpp);
585 for (y = 0; y < height; y++)
586 {
587 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
588 width * Bpp);
589 }
590 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
591 xfree(bmpdata);
592 continue;
593 }
594
595 in_uint8s(s, 2);/* pad */
596 in_uint16_le(s, size);
597 in_uint8s(s, 4);/* line_size, final_size */
598 in_uint8p(s, data, size);
599 bmpdata = (uint8*)xmalloc(width * height * Bpp);
600 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
601 {
602 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
603 }
604 xfree(bmpdata);
605 }
606}
607
608/* Process a palette update */
609static void
610process_palette(STREAM s)
611{
612 COLOURENTRY *entry;
613 COLOURMAP map;
614 HCOLOURMAP hmap;
615 int i;
616 uint8 data[1536];
617
618 in_uint8s(s, 2);/* pad */
619 in_uint16_le(s, map.ncolours);
620 in_uint8s(s, 2);/* pad */
621
622 map.colours = (COLOURENTRY*)data;
623
624 for (i = 0; i < map.ncolours; i++)
625 {
626 entry = &map.colours[i];
627 in_uint8(s, entry->red);
628 in_uint8(s, entry->green);
629 in_uint8(s, entry->blue);
630 }
631 hmap = ui_create_colourmap(&map);
632 ui_set_colourmap(hmap);
633}
634
635/* Process an update PDU */
636static void
637process_update_pdu(STREAM s)
638{
639 uint16 update_type;
640
641 in_uint16_le(s, update_type);
642 ui_begin_update();
643 switch (update_type)
644 {
645 case RDP_UPDATE_ORDERS:
646 process_orders(s);
647 break;
648
649 case RDP_UPDATE_BITMAP:
650 process_bitmap_updates(s);
651 break;
652
653 case RDP_UPDATE_PALETTE:
654 process_palette(s);
655 break;
656
657 case RDP_UPDATE_SYNCHRONIZE:
658 break;
659
660 default:
661 unimpl("update %d\n", update_type);
662 }
663 ui_end_update();
664}
665
666/* Process data PDU */
667void
668process_data_pdu(STREAM s)
669{
670 uint8 data_pdu_type;
671
672 in_uint8s(s, 8);/* shareid, pad, streamid, length */
673 in_uint8(s, data_pdu_type);
674 in_uint8s(s, 3);/* compress_type, compress_len */
675
676 switch (data_pdu_type)
677 {
678 case RDP_DATA_PDU_UPDATE:
679 process_update_pdu(s);
680 break;
681
682 case RDP_DATA_PDU_POINTER:
683 process_pointer_pdu(s);
684 break;
685
686 case RDP_DATA_PDU_BELL:
687 ui_bell();
688 break;
689
690 case RDP_DATA_PDU_LOGON:
691 /* User logged on */
692 break;
693
694 default:
695 unimpl("data PDU %d\n", data_pdu_type);
696 }
697}
698
699/* Process incoming packets */
700BOOL
701rdp_main_loop(void)
702{
703 uint8 type;
704 STREAM s;
705 BOOL cont = True;
706 while (cont)
707 {
708 s = rdp_recv(&type);
709 if (s == NULL)
710 return False;
711 switch (type)
712 {
713 case RDP_PDU_DEMAND_ACTIVE:
714 process_demand_active(s);
715 break;
716 case RDP_PDU_DEACTIVATE:
717 break;
718 case RDP_PDU_DATA:
719 process_data_pdu(s);
720 break;
721 case 0:
722 break;
723 default:
724 unimpl("PDU %d\n", type);
725 }
726 cont = next_packet < s->end;
727 }
728 return True;
729}
730
731/* Establish a connection up to the RDP layer */
732BOOL
733rdp_connect(char *server, uint32 flags, char *domain, char *password,
734 char *command, char *directory)
735{
736 if (!sec_connect(server))
737 return False;
738
739 rdp_send_logon_info(flags, domain, username, password, command, directory);
740 return True;
741}
742
743/* Disconnect from the RDP layer */
744void
745rdp_disconnect(void)
746{
747 sec_disconnect();
748}
diff --git a/noncore/net/opierdesktop/secure.cpp b/noncore/net/opierdesktop/secure.cpp
new file mode 100644
index 0000000..5e50f8d
--- a/dev/null
+++ b/noncore/net/opierdesktop/secure.cpp
@@ -0,0 +1,658 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP encryption and licensing
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "rdesktop.h"
22
23//#ifdef WITH_OPENSSL
24#include <openssl/rc4.h>
25#include <openssl/md5.h>
26#include <openssl/sha.h>
27#include <openssl/bn.h>
28//#else
29//#include "crypto/rc4.h"
30//#include "crypto/md5.h"
31//#include "crypto/sha.h"
32//#include "crypto/bn.h"
33//#endif
34
35extern char hostname[16];
36extern int g_width;
37extern int g_height;
38extern int keylayout;
39extern BOOL encryption;
40extern BOOL licence_issued;
41extern int server_bpp;
42
43static int rc4_key_len;
44static RC4_KEY rc4_decrypt_key;
45static RC4_KEY rc4_encrypt_key;
46
47static uint8 sec_sign_key[16];
48static uint8 sec_decrypt_key[16];
49static uint8 sec_encrypt_key[16];
50static uint8 sec_decrypt_update_key[16];
51static uint8 sec_encrypt_update_key[16];
52static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
53
54/*
55 * General purpose 48-byte transformation, using two 32-byte salts (generally,
56 * a client and server salt) and a global salt value used for padding.
57 * Both SHA1 and MD5 algorithms are used.
58 */
59void
60sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
61{
62 uint8 shasig[20];
63 uint8 pad[4];
64 SHA_CTX sha;
65 MD5_CTX md5;
66 int i;
67
68 for (i = 0; i < 3; i++)
69 {
70 memset(pad, salt + i, i + 1);
71
72 SHA1_Init(&sha);
73 SHA1_Update(&sha, pad, i + 1);
74 SHA1_Update(&sha, in, 48);
75 SHA1_Update(&sha, salt1, 32);
76 SHA1_Update(&sha, salt2, 32);
77 SHA1_Final(shasig, &sha);
78
79 MD5_Init(&md5);
80 MD5_Update(&md5, in, 48);
81 MD5_Update(&md5, shasig, 20);
82 MD5_Final(&out[i * 16], &md5);
83 }
84}
85
86/*
87 * Weaker 16-byte transformation, also using two 32-byte salts, but
88 * only using a single round of MD5.
89 */
90void
91sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
92{
93 MD5_CTX md5;
94
95 MD5_Init(&md5);
96 MD5_Update(&md5, in, 16);
97 MD5_Update(&md5, salt1, 32);
98 MD5_Update(&md5, salt2, 32);
99 MD5_Final(out, &md5);
100}
101
102/* Reduce key entropy from 64 to 40 bits */
103static void
104sec_make_40bit(uint8 * key)
105{
106 key[0] = 0xd1;
107 key[1] = 0x26;
108 key[2] = 0x9e;
109}
110
111/* Generate a session key and RC4 keys, given client and server randoms */
112static void
113sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)
114{
115 uint8 session_key[48];
116 uint8 temp_hash[48];
117 uint8 input[48];
118
119 /* Construct input data to hash */
120 memcpy(input, client_key, 24);
121 memcpy(input + 24, server_key, 24);
122
123 /* Generate session key - two rounds of sec_hash_48 */
124 sec_hash_48(temp_hash, input, client_key, server_key, 65);
125 sec_hash_48(session_key, temp_hash, client_key, server_key, 88);
126
127 /* Store first 16 bytes of session key, for generating signatures */
128 memcpy(sec_sign_key, session_key, 16);
129
130 /* Generate RC4 keys */
131 sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);
132 sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);
133
134 if (rc4_key_size == 1)
135 {
136 DEBUG(("40-bit encryption enabled\n"));
137 sec_make_40bit(sec_sign_key);
138 sec_make_40bit(sec_decrypt_key);
139 sec_make_40bit(sec_encrypt_key);
140 rc4_key_len = 8;
141 }
142 else
143 {
144 DEBUG(("128-bit encryption enabled\n"));
145 rc4_key_len = 16;
146 }
147
148 /* Save initial RC4 keys as update keys */
149 memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
150 memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
151
152 /* Initialise RC4 state arrays */
153 RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
154 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
155}
156
157static uint8 pad_54[40] = {
158 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
159 54, 54, 54,
160 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
161 54, 54, 54
162};
163
164static uint8 pad_92[48] = {
165 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
166 92, 92, 92, 92, 92, 92, 92,
167 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
168 92, 92, 92, 92, 92, 92, 92
169};
170
171/* Output a uint32 into a buffer (little-endian) */
172void
173buf_out_uint32(uint8 * buffer, uint32 value)
174{
175 buffer[0] = (value) & 0xff;
176 buffer[1] = (value >> 8) & 0xff;
177 buffer[2] = (value >> 16) & 0xff;
178 buffer[3] = (value >> 24) & 0xff;
179}
180
181/* Generate a signature hash, using a combination of SHA1 and MD5 */
182void
183sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
184{
185 uint8 shasig[20];
186 uint8 md5sig[16];
187 uint8 lenhdr[4];
188 SHA_CTX sha;
189 MD5_CTX md5;
190
191 buf_out_uint32(lenhdr, datalen);
192
193 SHA1_Init(&sha);
194 SHA1_Update(&sha, session_key, keylen);
195 SHA1_Update(&sha, pad_54, 40);
196 SHA1_Update(&sha, lenhdr, 4);
197 SHA1_Update(&sha, data, datalen);
198 SHA1_Final(shasig, &sha);
199
200 MD5_Init(&md5);
201 MD5_Update(&md5, session_key, keylen);
202 MD5_Update(&md5, pad_92, 48);
203 MD5_Update(&md5, shasig, 20);
204 MD5_Final(md5sig, &md5);
205
206 memcpy(signature, md5sig, siglen);
207}
208
209/* Update an encryption key - similar to the signing process */
210static void
211sec_update(uint8 * key, uint8 * update_key)
212{
213 uint8 shasig[20];
214 SHA_CTX sha;
215 MD5_CTX md5;
216 RC4_KEY update;
217
218 SHA1_Init(&sha);
219 SHA1_Update(&sha, update_key, rc4_key_len);
220 SHA1_Update(&sha, pad_54, 40);
221 SHA1_Update(&sha, key, rc4_key_len);
222 SHA1_Final(shasig, &sha);
223
224 MD5_Init(&md5);
225 MD5_Update(&md5, update_key, rc4_key_len);
226 MD5_Update(&md5, pad_92, 48);
227 MD5_Update(&md5, shasig, 20);
228 MD5_Final(key, &md5);
229
230 RC4_set_key(&update, rc4_key_len, key);
231 RC4(&update, rc4_key_len, key, key);
232
233 if (rc4_key_len == 8)
234 sec_make_40bit(key);
235}
236
237/* Encrypt data using RC4 */
238static void
239sec_encrypt(uint8 * data, int length)
240{
241 static int use_count;
242
243 if (use_count == 4096)
244 {
245 sec_update(sec_encrypt_key, sec_encrypt_update_key);
246 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
247 use_count = 0;
248 }
249
250 RC4(&rc4_encrypt_key, length, data, data);
251 use_count++;
252}
253
254/* Decrypt data using RC4 */
255static void
256sec_decrypt(uint8 * data, int length)
257{
258 static int use_count;
259
260 if (use_count == 4096)
261 {
262 sec_update(sec_decrypt_key, sec_decrypt_update_key);
263 RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
264 use_count = 0;
265 }
266
267 RC4(&rc4_decrypt_key, length, data, data);
268 use_count++;
269}
270
271static void
272reverse(uint8 * p, int len)
273{
274 int i, j;
275 uint8 temp;
276
277 for (i = 0, j = len - 1; i < j; i++, j--)
278 {
279 temp = p[i];
280 p[i] = p[j];
281 p[j] = temp;
282 }
283}
284
285/* Perform an RSA public key encryption operation */
286static void
287sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
288{
289 BN_CTX *ctx;
290 BIGNUM mod, exp, x, y;
291 uint8 inr[SEC_MODULUS_SIZE];
292 int outlen;
293
294 reverse(modulus, SEC_MODULUS_SIZE);
295 reverse(exponent, SEC_EXPONENT_SIZE);
296 memcpy(inr, in, len);
297 reverse(inr, len);
298
299 ctx = BN_CTX_new();
300 BN_init(&mod);
301 BN_init(&exp);
302 BN_init(&x);
303 BN_init(&y);
304
305 BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
306 BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
307 BN_bin2bn(inr, len, &x);
308 BN_mod_exp(&y, &x, &exp, &mod, ctx);
309 outlen = BN_bn2bin(&y, out);
310 reverse(out, outlen);
311 if (outlen < SEC_MODULUS_SIZE)
312 memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
313
314 BN_free(&y);
315 BN_clear_free(&x);
316 BN_free(&exp);
317 BN_free(&mod);
318 BN_CTX_free(ctx);
319}
320
321/* Initialise secure transport packet */
322STREAM
323sec_init(uint32 flags, int maxlen)
324{
325 int hdrlen;
326 STREAM s;
327
328 if (!licence_issued)
329 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
330 else
331 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
332 s = mcs_init(maxlen + hdrlen);
333 s_push_layer(s, sec_hdr, hdrlen);
334
335 return s;
336}
337
338/* Transmit secure transport packet */
339void
340sec_send(STREAM s, uint32 flags)
341{
342 int datalen;
343
344 s_pop_layer(s, sec_hdr);
345 if (!licence_issued || (flags & SEC_ENCRYPT))
346 out_uint32_le(s, flags);
347
348 if (flags & SEC_ENCRYPT)
349 {
350 flags &= ~SEC_ENCRYPT;
351 datalen = s->end - s->p - 8;
352
353#if WITH_DEBUG
354 DEBUG(("Sending encrypted packet:\n"));
355 hexdump(s->p + 8, datalen);
356#endif
357
358 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
359 sec_encrypt(s->p + 8, datalen);
360 }
361
362 mcs_send(s);
363}
364
365/* Transfer the client random to the server */
366static void
367sec_establish_key(void)
368{
369 uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
370 uint32 flags = SEC_CLIENT_RANDOM;
371 STREAM s;
372
373 s = sec_init(flags, 76);
374
375 out_uint32_le(s, length);
376 out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);
377 out_uint8s(s, SEC_PADDING_SIZE);
378
379 s_mark_end(s);
380 sec_send(s, flags);
381}
382
383/* Output connect initial data blob */
384static void
385sec_out_mcs_data(STREAM s)
386{
387 int hostlen = 2 * strlen(hostname);
388
389 if (hostlen > 30)
390 hostlen = 30;
391
392 out_uint16_be(s, 5);/* unknown */
393 out_uint16_be(s, 0x14);
394 out_uint8(s, 0x7c);
395 out_uint16_be(s, 1);
396
397 out_uint16_be(s, (158 | 0x8000));/* remaining length */
398
399 out_uint16_be(s, 8);/* length? */
400 out_uint16_be(s, 16);
401 out_uint8(s, 0);
402 out_uint16_le(s, 0xc001);
403 out_uint8(s, 0);
404
405 out_uint32_le(s, 0x61637544);/* "Duca" ?! */
406 out_uint16_be(s, (144 | 0x8000));/* remaining length */
407
408 /* Client information */
409 out_uint16_le(s, SEC_TAG_CLI_INFO);
410 out_uint16_le(s, 136);/* length */
411 out_uint16_le(s, 1);
412 out_uint16_le(s, 8);
413 out_uint16_le(s, g_width);
414 out_uint16_le(s, g_height);
415 out_uint16_le(s, 0xca01);
416 out_uint16_le(s, 0xaa03);
417 out_uint32_le(s, keylayout);
418 out_uint32_le(s, 419);/* client build? we are 419 compatible :-) */
419
420 /* Unicode name of client, padded to 32 bytes */
421 rdp_out_unistr(s, hostname, hostlen);
422 out_uint8s(s, 30 - hostlen);
423
424 out_uint32_le(s, 4);
425 out_uint32(s, 0);
426 out_uint32_le(s, 12);
427 out_uint8s(s, 64);/* reserved? 4 + 12 doublewords */
428
429 switch (server_bpp)
430 {
431 case 8:
432 out_uint16_le(s, 0xca01);
433 break;
434 case 15:
435 out_uint16_le(s, 0xca02);
436 break;
437 case 16:
438 out_uint16_le(s, 0xca03);
439 break;
440 case 24:
441 out_uint16_le(s, 0xca04);
442 break;
443 }
444 out_uint16(s, 0);
445
446 /* Client encryption settings */
447 out_uint16_le(s, SEC_TAG_CLI_CRYPT);
448 out_uint16_le(s, 8);/* length */
449 out_uint32_le(s, encryption ? 0x3 : 0);/* encryption supported, 128-bit supported */
450 s_mark_end(s);
451}
452
453/* Parse a public key structure */
454static BOOL
455sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
456{
457 uint32 magic, modulus_len;
458
459 in_uint32_le(s, magic);
460 if (magic != SEC_RSA_MAGIC)
461 {
462 error("RSA magic 0x%x\n", magic);
463 return False;
464 }
465
466 in_uint32_le(s, modulus_len);
467 if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
468 {
469 error("modulus len 0x%x\n", modulus_len);
470 return False;
471 }
472
473 in_uint8s(s, 8);/* modulus_bits, unknown */
474 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
475 in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
476 in_uint8s(s, SEC_PADDING_SIZE);
477
478 return s_check(s);
479}
480
481/* Parse a crypto information structure */
482static BOOL
483sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
484 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
485{
486 uint32 crypt_level, random_len, rsa_info_len;
487 uint16 tag, length;
488 uint8 *next_tag, *end;
489
490 in_uint32_le(s, *rc4_key_size);/* 1 = 40-bit, 2 = 128-bit */
491 in_uint32_le(s, crypt_level);/* 1 = low, 2 = medium, 3 = high */
492 if (crypt_level == 0)/* no encryptation */
493 return False;
494 in_uint32_le(s, random_len);
495 in_uint32_le(s, rsa_info_len);
496
497 if (random_len != SEC_RANDOM_SIZE)
498 {
499 error("random len %d\n", random_len);
500 return False;
501 }
502
503 in_uint8p(s, *server_random, random_len);
504
505 /* RSA info */
506 end = s->p + rsa_info_len;
507 if (end > s->end)
508 return False;
509
510 in_uint8s(s, 12);/* unknown */
511
512 while (s->p < end)
513 {
514 in_uint16_le(s, tag);
515 in_uint16_le(s, length);
516
517 next_tag = s->p + length;
518
519 switch (tag)
520 {
521 case SEC_TAG_PUBKEY:
522 if (!sec_parse_public_key(s, modulus, exponent))
523 return False;
524
525 break;
526
527 case SEC_TAG_KEYSIG:
528 /* Is this a Microsoft key that we just got? */
529 /* Care factor: zero! */
530 break;
531
532 default:
533 unimpl("crypt tag 0x%x\n", tag);
534 }
535
536 s->p = next_tag;
537 }
538
539 return s_check_end(s);
540}
541
542/* Process crypto information blob */
543static void
544sec_process_crypt_info(STREAM s)
545{
546 uint8 *server_random, *modulus, *exponent;
547 uint8 client_random[SEC_RANDOM_SIZE];
548 uint32 rc4_key_size;
549
550 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
551 return;
552
553 /* Generate a client random, and hence determine encryption keys */
554 generate_random(client_random);
555 sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE, modulus, exponent);
556 sec_generate_keys(client_random, server_random, rc4_key_size);
557}
558
559/* Process connect response data blob */
560static void
561sec_process_mcs_data(STREAM s)
562{
563 uint16 tag, length;
564 uint8 *next_tag;
565 uint8 len;
566
567 in_uint8s(s, 21);/* header */
568 in_uint8(s, len);
569 if (len & 0x80)
570 in_uint8(s, len);
571
572 while (s->p < s->end)
573 {
574 in_uint16_le(s, tag);
575 in_uint16_le(s, length);
576
577 if (length <= 4)
578 return;
579
580 next_tag = s->p + length - 4;
581
582 switch (tag)
583 {
584 case SEC_TAG_SRV_INFO:
585 case SEC_TAG_SRV_3:
586 break;
587
588 case SEC_TAG_SRV_CRYPT:
589 sec_process_crypt_info(s);
590 break;
591
592 default:
593 unimpl("response tag 0x%x\n", tag);
594 }
595
596 s->p = next_tag;
597 }
598}
599
600/* Receive secure transport packet */
601STREAM
602sec_recv(void)
603{
604 uint32 sec_flags;
605 STREAM s;
606
607 while ((s = mcs_recv()) != NULL)
608 {
609 if (encryption || !licence_issued)
610 {
611 in_uint32_le(s, sec_flags);
612
613 if (sec_flags & SEC_LICENCE_NEG)
614 {
615 licence_process(s);
616 continue;
617 }
618
619 if (sec_flags & SEC_ENCRYPT)
620 {
621 in_uint8s(s, 8);/* signature */
622 sec_decrypt(s->p, s->end - s->p);
623 }
624 }
625
626 return s;
627 }
628
629 return NULL;
630}
631
632/* Establish a secure connection */
633BOOL
634sec_connect(char *server)
635{
636 struct stream mcs_data;
637
638 /* We exchange some RDP data during the MCS-Connect */
639 mcs_data.size = 512;
640 mcs_data.p = mcs_data.data = (unsigned char*)xmalloc(mcs_data.size);
641 sec_out_mcs_data(&mcs_data);
642
643 if (!mcs_connect(server, &mcs_data))
644 return False;
645
646 sec_process_mcs_data(&mcs_data);
647 if (encryption)
648 sec_establish_key();
649 xfree(mcs_data.data);
650 return True;
651}
652
653/* Disconnect a connection */
654void
655sec_disconnect(void)
656{
657 mcs_disconnect();
658}
diff --git a/noncore/net/opierdesktop/tcp.cpp b/noncore/net/opierdesktop/tcp.cpp
new file mode 100644
index 0000000..0a2ca3e
--- a/dev/null
+++ b/noncore/net/opierdesktop/tcp.cpp
@@ -0,0 +1,181 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - TCP layer
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21 #include <unistd.h> /* select read write close */
22 #include <sys/socket.h> /* socket connect setsockopt */
23 #include <sys/time.h> /* timeval */
24 #include <netdb.h> /* gethostbyname */
25 #include <netinet/in.h> /* sockaddr_in */
26 #include <netinet/tcp.h>/* TCP_NODELAY */
27 #include <arpa/inet.h> /* inet_addr */
28#include <fcntl.h>
29 #include <errno.h> /* errno */
30#include "rdesktop.h"
31
32#ifndef INADDR_NONE
33#define INADDR_NONE ((unsigned long) -1)
34#endif
35
36static int sock;
37static struct stream in;
38static struct stream out;
39extern int tcp_port_rdp;
40
41/* Initialise TCP transport data packet */
42STREAM
43tcp_init(unsigned int maxlen)
44{
45 if (maxlen > out.size)
46 {
47 out.data = (unsigned char*)xrealloc(out.data, maxlen);
48 out.size = maxlen;
49 }
50
51 out.p = out.data;
52 out.end = out.data + out.size;
53 return &out;
54}
55
56/* Send TCP transport data packet */
57void
58tcp_send(STREAM s)
59{
60 int length = s->end - s->data;
61 int sent, total = 0;
62
63 while (total < length)
64 {
65 sent = send(sock, s->data + total, length - total, 0);
66 if (sent == -1 && errno == EWOULDBLOCK)
67 {
68 usleep(1000);
69 }
70 else if (sent <= 0)
71 {
72 error("send: %s\n", strerror(errno));
73 return;
74 }
75 else
76 total += sent;
77 }
78}
79
80/* Receive a message on the TCP layer */
81STREAM
82tcp_recv(unsigned int length)
83{
84 int rcvd = 0;
85
86 if (length > in.size)
87 {
88 in.data = (unsigned char*)xrealloc(in.data, length);
89 in.size = length;
90 }
91
92 in.end = in.p = in.data;
93
94 while (length > 0)
95 {
96 if (!ui_select(sock))
97 /* User quit */
98 return NULL;
99
100 rcvd = recv(sock, in.end, length, 0);
101 if (rcvd == -1 && errno == EWOULDBLOCK)
102 {
103 usleep(1000);
104 }
105 else if (rcvd == -1)
106 {
107 error("recv: %s\n", strerror(errno));
108 return NULL;
109 }
110 else if (rcvd == 0)
111 return NULL;
112 else
113 {
114 in.end += rcvd;
115 length -= rcvd;
116 }
117 }
118
119 return &in;
120}
121
122/* Establish a connection on the TCP layer */
123BOOL
124tcp_connect(char *server)
125{
126 struct hostent *nslookup;
127 struct sockaddr_in servaddr;
128 int l_true = 1;
129
130 if ((nslookup = gethostbyname(server)) != NULL)
131 {
132 memcpy(&servaddr.sin_addr, nslookup->h_addr, sizeof(servaddr.sin_addr));
133 }
134 else if ((servaddr.sin_addr.s_addr = inet_addr(server)) == INADDR_NONE)
135 {
136 error("%s: unable to resolve host\n", server);
137 return False;
138 }
139
140 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
141 {
142 error("socket: %s\n", strerror(errno));
143 return False;
144 }
145
146 servaddr.sin_family = AF_INET;
147 servaddr.sin_port = htons(tcp_port_rdp);
148
149 if (connect(sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)
150 {
151 error("connect: %s\n", strerror(errno));
152 close(sock);
153 return False;
154 }
155
156 /* set non blocking */
157 {
158 int op;
159 op = fcntl(sock, F_GETFL);
160 op |= O_NONBLOCK;
161 fcntl(sock, F_SETFL, op);
162 }
163
164 //fcntl(sock, O_NONBLOCK);
165 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &l_true, sizeof(l_true));
166
167 in.size = 4096;
168 in.data = (unsigned char*)xmalloc(in.size);
169
170 out.size = 4096;
171 out.data = (unsigned char*)xmalloc(out.size);
172
173 return True;
174}
175
176/* Disconnect on the TCP layer */
177void
178tcp_disconnect(void)
179{
180 close(sock);
181}
diff --git a/noncore/net/opierdesktop/types.h b/noncore/net/opierdesktop/types.h
new file mode 100644
index 0000000..4cb59e6
--- a/dev/null
+++ b/noncore/net/opierdesktop/types.h
@@ -0,0 +1,110 @@
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Common data types
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21typedef int BOOL;
22
23#ifndef True
24#define True (1)
25#define False (0)
26#endif
27
28typedef unsigned char uint8;
29typedef signed char sint8;
30typedef unsigned short uint16;
31typedef signed short sint16;
32typedef unsigned int uint32;
33typedef signed int sint32;
34
35typedef void *HBITMAP;
36typedef void *HGLYPH;
37typedef void *HCOLOURMAP;
38typedef void *HCURSOR;
39
40typedef struct _COLOURENTRY
41{
42 uint8 red;
43 uint8 green;
44 uint8 blue;
45
46}
47COLOURENTRY;
48
49typedef struct _COLOURMAP
50{
51 uint16 ncolours;
52 COLOURENTRY *colours;
53
54}
55COLOURMAP;
56
57typedef struct _BOUNDS
58{
59 sint16 left;
60 sint16 top;
61 sint16 right;
62 sint16 bottom;
63
64}
65BOUNDS;
66
67typedef struct _PEN
68{
69 uint8 style;
70 uint8 width;
71 uint32 colour;
72
73}
74PEN;
75
76typedef struct _BRUSH
77{
78 uint8 xorigin;
79 uint8 yorigin;
80 uint8 style;
81 uint8 pattern[8];
82
83}
84BRUSH;
85
86typedef struct _FONTGLYPH
87{
88 sint16 offset;
89 sint16 baseline;
90 uint16 width;
91 uint16 height;
92 HBITMAP pixmap;
93
94}
95FONTGLYPH;
96
97typedef struct _DATABLOB
98{
99 void *data;
100 int size;
101
102}
103DATABLOB;
104
105typedef struct _key_translation
106{
107 uint8 scancode;
108 uint16 modifiers;
109}
110key_translation;