author | mickeyl <mickeyl> | 2003-08-10 15:17:24 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-08-10 15:17:24 (UTC) |
commit | 1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f (patch) (unidiff) | |
tree | 73b54db5d3aa3e40f4159079c14c8fca90a76c1e | |
parent | df6337abb65463b466435a526bf62108e72a60f7 (diff) | |
download | opie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.zip opie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.tar.gz opie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.tar.bz2 |
initial import of qtrdesktop - not yet opiefied but working
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 | *~ | ||
3 | Makefile* | ||
4 | moc_* | ||
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 | |||
25 | static uint32 | ||
26 | cvalx(unsigned char **input, int Bpp) | ||
27 | { | ||
28 | uint32 rv = 0; | ||
29 | memcpy(&rv, *input, Bpp); | ||
30 | *input += Bpp; | ||
31 | return rv; | ||
32 | } | ||
33 | |||
34 | static void | ||
35 | setli(unsigned char *input, int offset, uint32 value, int Bpp) | ||
36 | { | ||
37 | input += offset * Bpp; | ||
38 | memcpy(input, &value, Bpp); | ||
39 | } | ||
40 | |||
41 | static uint32 | ||
42 | getli(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 | |||
70 | BOOL | ||
71 | bitmap_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 */ | ||
27 | static HBITMAP bmpcache[3][600]; | ||
28 | |||
29 | /* Retrieve a bitmap from the cache */ | ||
30 | HBITMAP | ||
31 | cache_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 */ | ||
47 | void | ||
48 | cache_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 */ | ||
68 | static FONTGLYPH fontcache[12][256]; | ||
69 | |||
70 | /* Retrieve a glyph from the font cache */ | ||
71 | FONTGLYPH * | ||
72 | cache_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 */ | ||
88 | void | ||
89 | cache_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 */ | ||
114 | static DATABLOB textcache[256]; | ||
115 | |||
116 | /* Retrieve a text item from the cache */ | ||
117 | DATABLOB * | ||
118 | cache_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 */ | ||
134 | void | ||
135 | cache_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 */ | ||
157 | static uint8 deskcache[0x38400]; | ||
158 | |||
159 | /* Retrieve desktop data from the cache */ | ||
160 | uint8 * | ||
161 | cache_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 */ | ||
175 | void | ||
176 | cache_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 */ | ||
198 | static HCURSOR cursorcache[0x20]; | ||
199 | |||
200 | /* Retrieve cursor from cache */ | ||
201 | HCURSOR | ||
202 | cache_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 */ | ||
218 | void | ||
219 | cache_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 */ | ||
25 | enum 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 */ | ||
35 | enum 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 */ | ||
99 | enum 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 | |||
107 | enum 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 | |||
119 | enum 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 | |||
127 | enum 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 | |||
135 | enum RDP_POINTER_PDU_TYPE | ||
136 | { | ||
137 | RDP_POINTER_MOVE = 3, | ||
138 | RDP_POINTER_COLOR = 6, | ||
139 | RDP_POINTER_CACHED = 7 | ||
140 | }; | ||
141 | |||
142 | enum 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 */ | ||
24 | static void | ||
25 | iso_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 */ | ||
46 | static STREAM | ||
47 | iso_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 */ | ||
87 | STREAM | ||
88 | iso_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 */ | ||
99 | void | ||
100 | iso_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 */ | ||
119 | STREAM | ||
120 | iso_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 */ | ||
139 | BOOL | ||
140 | iso_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 */ | ||
165 | void | ||
166 | iso_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 | |||
29 | extern char username[16]; | ||
30 | extern char hostname[16]; | ||
31 | |||
32 | static uint8 licence_key[16]; | ||
33 | static uint8 licence_sign_key[16]; | ||
34 | |||
35 | BOOL licence_issued = False; | ||
36 | |||
37 | /* Generate a session key and RC4 keys, given client and server randoms */ | ||
38 | static void | ||
39 | licence_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 | |||
55 | static void | ||
56 | licence_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 */ | ||
63 | static void | ||
64 | licence_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 */ | ||
103 | static void | ||
104 | licence_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 */ | ||
140 | static void | ||
141 | licence_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 */ | ||
179 | static void | ||
180 | licence_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 */ | ||
206 | static BOOL | ||
207 | licence_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 */ | ||
227 | static void | ||
228 | licence_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 */ | ||
259 | static void | ||
260 | licence_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 */ | ||
283 | void | ||
284 | licence_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 | |||
23 | uint16 mcs_userid; | ||
24 | |||
25 | /* Parse an ASN.1 BER header */ | ||
26 | static BOOL | ||
27 | ber_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 */ | ||
61 | static void | ||
62 | ber_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 */ | ||
83 | static void | ||
84 | ber_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) */ | ||
91 | static void | ||
92 | mcs_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) */ | ||
106 | static BOOL | ||
107 | mcs_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) */ | ||
118 | static void | ||
119 | mcs_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) */ | ||
146 | static BOOL | ||
147 | mcs_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) */ | ||
186 | static void | ||
187 | mcs_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) */ | ||
202 | static void | ||
203 | mcs_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) */ | ||
216 | static BOOL | ||
217 | mcs_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) */ | ||
247 | static void | ||
248 | mcs_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) */ | ||
263 | static BOOL | ||
264 | mcs_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 */ | ||
295 | STREAM | ||
296 | mcs_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 */ | ||
307 | void | ||
308 | mcs_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 */ | ||
326 | STREAM | ||
327 | mcs_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 */ | ||
356 | BOOL | ||
357 | mcs_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 */ | ||
390 | void | ||
391 | mcs_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 @@ | |||
1 | Package: opie-rdesktop | ||
2 | Files: bin/ordesktop pics/opierdesktop apps/Applications/opierdesktop.desktop | ||
3 | Priority: optional | ||
4 | Section: opie/applications | ||
5 | Maintainer: Michael 'Mickey' Lauer <mickeyl@handhelds.org> | ||
6 | Architecture: arm | ||
7 | Version: 1.2.0-$SUB_VERSION | ||
8 | Depends: task-opie-minimal | ||
9 | Description: 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 @@ | |||
1 | TEMPLATE = app | ||
2 | DESTDIR = $(OPIEDIR)/bin | ||
3 | CONFIG = qt warn_on debug | ||
4 | |||
5 | HEADERS += constants.h orders.h parse.h proto.h qtwin.h rdesktop.h types.h | ||
6 | SOURCES += 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 | |||
18 | INCLUDEPATH += $(OPIEDIR)/include | ||
19 | DEPENDPATH += $(OPIEDIR)/include | ||
20 | LIBS += -lqpe -lm -lcrypto | ||
21 | INTERFACES = | ||
22 | TARGET = ordesktop | ||
23 | QMAKE_CXXFLAGS += -DSHARP=1 -DWITH_OPENSSL=1 | ||
24 | |||
25 | include ( $(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 | |||
24 | extern uint8 *next_packet; | ||
25 | static RDP_ORDER_STATE order_state; | ||
26 | |||
27 | /* Read field indicating which parameters are present */ | ||
28 | static void | ||
29 | rdp_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) */ | ||
56 | static void | ||
57 | rdp_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 */ | ||
73 | static void | ||
74 | rdp_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 */ | ||
86 | static BOOL | ||
87 | rdp_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 */ | ||
117 | static BOOL | ||
118 | rdp_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 */ | ||
133 | static BOOL | ||
134 | rdp_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 */ | ||
155 | static void | ||
156 | process_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 */ | ||
180 | static void | ||
181 | process_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 */ | ||
214 | static void | ||
215 | process_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 */ | ||
245 | static void | ||
246 | process_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 */ | ||
284 | static void | ||
285 | process_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 */ | ||
324 | static void | ||
325 | process_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 */ | ||
360 | static void | ||
361 | process_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 */ | ||
406 | static void | ||
407 | process_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 */ | ||
465 | static int | ||
466 | parse_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 */ | ||
483 | static void | ||
484 | process_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 */ | ||
561 | static void | ||
562 | process_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 */ | ||
643 | static void | ||
644 | process_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 */ | ||
676 | static void | ||
677 | process_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 */ | ||
707 | static void | ||
708 | process_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 */ | ||
738 | static void | ||
739 | process_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 */ | ||
769 | static void | ||
770 | process_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 */ | ||
808 | void | ||
809 | process_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 */ | ||
935 | void | ||
936 | reset_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 | |||
30 | enum 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 | |||
44 | enum 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 | |||
52 | typedef struct _DESTBLT_ORDER | ||
53 | { | ||
54 | sint16 x; | ||
55 | sint16 y; | ||
56 | sint16 cx; | ||
57 | sint16 cy; | ||
58 | uint8 opcode; | ||
59 | |||
60 | } | ||
61 | DESTBLT_ORDER; | ||
62 | |||
63 | typedef 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 | } | ||
75 | PATBLT_ORDER; | ||
76 | |||
77 | typedef 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 | } | ||
88 | SCREENBLT_ORDER; | ||
89 | |||
90 | typedef 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 | } | ||
102 | LINE_ORDER; | ||
103 | |||
104 | typedef struct _RECT_ORDER | ||
105 | { | ||
106 | sint16 x; | ||
107 | sint16 y; | ||
108 | sint16 cx; | ||
109 | sint16 cy; | ||
110 | uint32 colour; | ||
111 | |||
112 | } | ||
113 | RECT_ORDER; | ||
114 | |||
115 | typedef struct _DESKSAVE_ORDER | ||
116 | { | ||
117 | uint32 offset; | ||
118 | sint16 left; | ||
119 | sint16 top; | ||
120 | sint16 right; | ||
121 | sint16 bottom; | ||
122 | uint8 action; | ||
123 | |||
124 | } | ||
125 | DESKSAVE_ORDER; | ||
126 | |||
127 | typedef 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 | } | ||
145 | TRIBLT_ORDER; | ||
146 | |||
147 | typedef 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 | } | ||
161 | MEMBLT_ORDER; | ||
162 | |||
163 | #define MAX_DATA 256 | ||
164 | |||
165 | typedef 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 | } | ||
176 | POLYLINE_ORDER; | ||
177 | |||
178 | #define MAX_TEXT 256 | ||
179 | |||
180 | typedef 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 | } | ||
202 | TEXT2_ORDER; | ||
203 | |||
204 | typedef 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 | } | ||
221 | RDP_ORDER_STATE; | ||
222 | |||
223 | typedef 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 | } | ||
235 | RDP_RAW_BMPCACHE_ORDER; | ||
236 | |||
237 | typedef 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 | } | ||
253 | RDP_BMPCACHE_ORDER; | ||
254 | |||
255 | #define MAX_GLYPH 32 | ||
256 | |||
257 | typedef 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 | } | ||
267 | RDP_FONT_GLYPH; | ||
268 | |||
269 | #define MAX_GLYPHS 256 | ||
270 | |||
271 | typedef struct _RDP_FONTCACHE_ORDER | ||
272 | { | ||
273 | uint8 font; | ||
274 | uint8 nglyphs; | ||
275 | RDP_FONT_GLYPH glyphs[MAX_GLYPHS]; | ||
276 | |||
277 | } | ||
278 | RDP_FONTCACHE_ORDER; | ||
279 | |||
280 | typedef struct _RDP_COLCACHE_ORDER | ||
281 | { | ||
282 | uint8 cache_id; | ||
283 | COLOURMAP map; | ||
284 | |||
285 | } | ||
286 | RDP_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 */ | ||
22 | typedef 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 */ | ||
2 | BOOL bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, | ||
3 | int Bpp); | ||
4 | /* cache.c */ | ||
5 | HBITMAP cache_get_bitmap(uint8 cache_id, uint16 cache_idx); | ||
6 | void cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap); | ||
7 | FONTGLYPH *cache_get_font(uint8 font, uint16 character); | ||
8 | void cache_put_font(uint8 font, uint16 character, uint16 offset, uint16 baseline, uint16 width, | ||
9 | uint16 height, HGLYPH pixmap); | ||
10 | DATABLOB *cache_get_text(uint8 cache_id); | ||
11 | void cache_put_text(uint8 cache_id, void *data, int length); | ||
12 | uint8 *cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel); | ||
13 | void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, | ||
14 | uint8 * data); | ||
15 | HCURSOR cache_get_cursor(uint16 cache_idx); | ||
16 | void cache_put_cursor(uint16 cache_idx, HCURSOR cursor); | ||
17 | /* ewmhints.c */ | ||
18 | int get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height); | ||
19 | /* iso.c */ | ||
20 | STREAM iso_init(int length); | ||
21 | void iso_send(STREAM s); | ||
22 | STREAM iso_recv(void); | ||
23 | BOOL iso_connect(char *server); | ||
24 | void iso_disconnect(void); | ||
25 | /* licence.c */ | ||
26 | void licence_process(STREAM s); | ||
27 | /* mcs.c */ | ||
28 | STREAM mcs_init(int length); | ||
29 | void mcs_send(STREAM s); | ||
30 | STREAM mcs_recv(void); | ||
31 | BOOL mcs_connect(char *server, STREAM mcs_data); | ||
32 | void mcs_disconnect(void); | ||
33 | /* orders.c */ | ||
34 | void process_orders(STREAM s); | ||
35 | void reset_order_state(void); | ||
36 | /* rdesktop.c */ | ||
37 | int main(int argc, char *argv[]); | ||
38 | void generate_random(uint8 * random); | ||
39 | void *xmalloc(int size); | ||
40 | void *xrealloc(void *oldmem, int size); | ||
41 | void xfree(void *mem); | ||
42 | void error(char *format, ...); | ||
43 | void warning(char *format, ...); | ||
44 | void unimpl(char *format, ...); | ||
45 | void hexdump(unsigned char *p, unsigned int len); | ||
46 | int load_licence(unsigned char **data); | ||
47 | void save_licence(unsigned char *data, int length); | ||
48 | /* rdp.c */ | ||
49 | void rdp_out_unistr(STREAM s, char *string, int len); | ||
50 | void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, | ||
51 | uint16 param2); | ||
52 | BOOL rdp_main_loop(void); | ||
53 | BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, char *command, | ||
54 | char *directory); | ||
55 | void rdp_disconnect(void); | ||
56 | /* secure.c */ | ||
57 | void sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt); | ||
58 | void sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2); | ||
59 | void buf_out_uint32(uint8 * buffer, uint32 value); | ||
60 | void sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, | ||
61 | int datalen); | ||
62 | STREAM sec_init(uint32 flags, int maxlen); | ||
63 | void sec_send(STREAM s, uint32 flags); | ||
64 | STREAM sec_recv(void); | ||
65 | BOOL sec_connect(char *server); | ||
66 | void sec_disconnect(void); | ||
67 | /* tcp.c */ | ||
68 | STREAM tcp_init(unsigned int maxlen); | ||
69 | void tcp_send(STREAM s); | ||
70 | STREAM tcp_recv(unsigned int length); | ||
71 | BOOL tcp_connect(char *server); | ||
72 | void tcp_disconnect(void); | ||
73 | /* xkeymap.c */ | ||
74 | void xkeymap_init(void); | ||
75 | BOOL handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed); | ||
76 | key_translation xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state); | ||
77 | uint16 xkeymap_translate_button(unsigned int button); | ||
78 | char *get_ksname(uint32 keysym); | ||
79 | void ensure_remote_modifiers(uint32 ev_time, key_translation tr); | ||
80 | void reset_modifier_keys(unsigned int state); | ||
81 | void rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode); | ||
82 | /* xwin.c */ | ||
83 | BOOL get_key_state(unsigned int state, uint32 keysym); | ||
84 | BOOL ui_init(void); | ||
85 | void ui_deinit(void); | ||
86 | BOOL ui_create_window(void); | ||
87 | void ui_destroy_window(void); | ||
88 | void xwin_toggle_fullscreen(void); | ||
89 | int ui_select(int rdp_socket); | ||
90 | void ui_move_pointer(int x, int y); | ||
91 | HBITMAP ui_create_bitmap(int width, int height, uint8 * data); | ||
92 | void ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data); | ||
93 | void ui_destroy_bitmap(HBITMAP bmp); | ||
94 | HGLYPH ui_create_glyph(int width, int height, uint8 * data); | ||
95 | void ui_destroy_glyph(HGLYPH glyph); | ||
96 | HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask, | ||
97 | uint8 * xormask); | ||
98 | void ui_set_cursor(HCURSOR cursor); | ||
99 | void ui_destroy_cursor(HCURSOR cursor); | ||
100 | HCOLOURMAP ui_create_colourmap(COLOURMAP * colours); | ||
101 | void ui_destroy_colourmap(HCOLOURMAP map); | ||
102 | void ui_set_colourmap(HCOLOURMAP map); | ||
103 | void ui_begin_update(void); | ||
104 | void ui_end_update(void); | ||
105 | void ui_set_clip(int x, int y, int cx, int cy); | ||
106 | void ui_reset_clip(void); | ||
107 | void ui_bell(void); | ||
108 | void ui_destblt(uint8 opcode, int x, int y, int cx, int cy); | ||
109 | void ui_patblt(uint8 opcode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour, | ||
110 | int fgcolour); | ||
111 | void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy); | ||
112 | void ui_memblt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy); | ||
113 | void 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); | ||
115 | void ui_line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen); | ||
116 | void ui_rect(int x, int y, int cx, int cy, int colour); | ||
117 | void 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); | ||
120 | void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy); | ||
121 | void 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 | |||
45 | uint32 flags; | ||
46 | char server[64] = ""; | ||
47 | char domain[16] = ""; | ||
48 | char password[16] = ""; | ||
49 | char shell[128] = ""; | ||
50 | char directory[32] = ""; | ||
51 | |||
52 | extern int g_width; | ||
53 | extern int g_height; | ||
54 | extern int server_bpp; | ||
55 | extern BOOL fullscreen; | ||
56 | extern char username[]; | ||
57 | int global_sock; | ||
58 | |||
59 | QSocketNotifier* SocketNotifier; | ||
60 | #ifdef SHARP | ||
61 | QPEApplication* App; | ||
62 | #else | ||
63 | QApplication* App; | ||
64 | #endif | ||
65 | QMyMainWindow* MW; | ||
66 | QMyScrollView* SV; | ||
67 | struct QColorMap | ||
68 | { | ||
69 | uint32 RGBColors[256]; | ||
70 | int NumColors; | ||
71 | }; | ||
72 | QColorMap* CM; | ||
73 | uint8* BS; | ||
74 | int clipx; | ||
75 | int clipy; | ||
76 | int clipcx; | ||
77 | int clipcy; | ||
78 | |||
79 | struct bitmap | ||
80 | { | ||
81 | int w; | ||
82 | int h; | ||
83 | uint8* data; | ||
84 | }; | ||
85 | |||
86 | BOOL owncolmap = False; | ||
87 | |||
88 | //***************************************************************************** | ||
89 | void 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 | //***************************************************************************** | ||
103 | QMyDialog::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 | //***************************************************************************** | ||
254 | QMyDialog::~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 | //***************************************************************************** | ||
267 | void 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 | //***************************************************************************** | ||
287 | void 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 | //***************************************************************************** | ||
299 | void QMyDialog::CancelClicked() | ||
300 | { | ||
301 | done(0); | ||
302 | } | ||
303 | |||
304 | //***************************************************************************** | ||
305 | void 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 | //***************************************************************************** | ||
325 | void 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 | //***************************************************************************** | ||
345 | void WriteString(QFile* File, QString* Line) | ||
346 | { | ||
347 | File->writeBlock((const char*)(*Line), Line->length()); | ||
348 | } | ||
349 | |||
350 | //***************************************************************************** | ||
351 | void 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 | //***************************************************************************** | ||
409 | void 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 | //***************************************************************************** | ||
435 | void 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 | //***************************************************************************** | ||
457 | void QMyDialog::ListBoxSelected(int /*index*/) | ||
458 | { | ||
459 | } | ||
460 | |||
461 | //***************************************************************************** | ||
462 | void 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 | //***************************************************************************** | ||
630 | QMyScrollView::QMyScrollView() : QScrollView() | ||
631 | { | ||
632 | } | ||
633 | |||
634 | //***************************************************************************** | ||
635 | QMyScrollView::~QMyScrollView() | ||
636 | { | ||
637 | } | ||
638 | |||
639 | //***************************************************************************** | ||
640 | void 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 | //***************************************************************************** | ||
658 | void 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 | //***************************************************************************** | ||
676 | void QMyScrollView::showEvent(QShowEvent* e) | ||
677 | { | ||
678 | QScrollView::showEvent(e); | ||
679 | } | ||
680 | |||
681 | //***************************************************************************** | ||
682 | void QMyScrollView::show() | ||
683 | { | ||
684 | QScrollView::show(); | ||
685 | } | ||
686 | |||
687 | //***************************************************************************** | ||
688 | void QMyScrollView::polish() | ||
689 | { | ||
690 | QScrollView::polish(); | ||
691 | } | ||
692 | |||
693 | //***************************************************************************** | ||
694 | void 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 | //***************************************************************************** | ||
753 | QMyMainWindow::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 | //***************************************************************************** | ||
764 | QMyMainWindow::~QMyMainWindow() | ||
765 | { | ||
766 | delete PopupMenu; | ||
767 | } | ||
768 | |||
769 | //***************************************************************************** | ||
770 | void 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 | //***************************************************************************** | ||
791 | void 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 | //***************************************************************************** | ||
837 | void 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 | //***************************************************************************** | ||
859 | void 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 | //***************************************************************************** | ||
873 | void 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 | //***************************************************************************** | ||
886 | void 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 | //***************************************************************************** | ||
897 | uint8 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 | //***************************************************************************** | ||
922 | uint8 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 | //***************************************************************************** | ||
931 | void 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 | ||
943 | bool 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 | //***************************************************************************** | ||
966 | void 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 | //***************************************************************************** | ||
1000 | void QMyMainWindow::closeEvent(QCloseEvent* e) | ||
1001 | { | ||
1002 | e->accept(); | ||
1003 | } | ||
1004 | |||
1005 | //***************************************************************************** | ||
1006 | void QMyMainWindow::dataReceived() | ||
1007 | { | ||
1008 | if (rdp_main_loop()) | ||
1009 | return; | ||
1010 | else | ||
1011 | SV->close(); | ||
1012 | } | ||
1013 | |||
1014 | //***************************************************************************** | ||
1015 | void 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 | /* | ||
1024 | BOOL 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 | /* | ||
1046 | void ui_deinit(void) | ||
1047 | { | ||
1048 | delete App; | ||
1049 | } | ||
1050 | */ | ||
1051 | |||
1052 | /* | ||
1053 | BOOL 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 | /* | ||
1082 | void 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 */ | ||
1093 | int ui_select(int rdp_socket) | ||
1094 | { | ||
1095 | global_sock = rdp_socket; | ||
1096 | return 1; | ||
1097 | } | ||
1098 | |||
1099 | //***************************************************************************** | ||
1100 | void ui_move_pointer(int /*x*/, int /*y*/) | ||
1101 | { | ||
1102 | } | ||
1103 | |||
1104 | //***************************************************************************** | ||
1105 | HBITMAP 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 | //***************************************************************************** | ||
1124 | void 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 | //***************************************************************************** | ||
1138 | void 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 | //***************************************************************************** | ||
1152 | bool 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 | //***************************************************************************** | ||
1170 | void 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 | //***************************************************************************** | ||
1177 | HGLYPH 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 | //***************************************************************************** | ||
1197 | void 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 | //***************************************************************************** | ||
1211 | HCURSOR 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 | //***************************************************************************** | ||
1219 | void ui_set_cursor(HCURSOR /*cursor*/) | ||
1220 | { | ||
1221 | } | ||
1222 | |||
1223 | //***************************************************************************** | ||
1224 | void ui_destroy_cursor(HCURSOR /*cursor*/) | ||
1225 | { | ||
1226 | } | ||
1227 | |||
1228 | //***************************************************************************** | ||
1229 | HCOLOURMAP 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 | //***************************************************************************** | ||
1249 | void ui_destroy_colourmap(HCOLOURMAP /*map*/) | ||
1250 | { | ||
1251 | } | ||
1252 | |||
1253 | //***************************************************************************** | ||
1254 | void ui_set_colourmap(HCOLOURMAP /*map*/) | ||
1255 | { | ||
1256 | } | ||
1257 | |||
1258 | //***************************************************************************** | ||
1259 | void ui_begin_update(void) | ||
1260 | { | ||
1261 | } | ||
1262 | |||
1263 | //***************************************************************************** | ||
1264 | void ui_end_update(void) | ||
1265 | { | ||
1266 | } | ||
1267 | |||
1268 | //***************************************************************************** | ||
1269 | void 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 | //***************************************************************************** | ||
1278 | void ui_reset_clip(void) | ||
1279 | { | ||
1280 | clipx = 0; | ||
1281 | clipy = 0; | ||
1282 | clipcx = g_width; | ||
1283 | clipcy = g_height; | ||
1284 | } | ||
1285 | |||
1286 | //***************************************************************************** | ||
1287 | void ui_bell(void) | ||
1288 | { | ||
1289 | App->beep(); | ||
1290 | } | ||
1291 | |||
1292 | //***************************************************************************** | ||
1293 | void 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 | ||
1305 | void 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 | //***************************************************************************** | ||
1315 | void 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 | //***************************************************************************** | ||
1322 | void 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 | //***************************************************************************** | ||
1349 | void 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 | //***************************************************************************** | ||
1367 | void 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 | ||
1385 | void 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 | ||
1393 | void 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 | //***************************************************************************** | ||
1472 | void 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 | //***************************************************************************** | ||
1517 | void 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 | //***************************************************************************** | ||
1588 | void 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 | //***************************************************************************** | ||
1602 | void 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 | //***************************************************************************** | ||
1615 | int 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 | |||
1666 | int 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 | |||
12 | class QMyConnectionItem | ||
13 | { | ||
14 | public: | ||
15 | QString ServerName; | ||
16 | QString UserName; | ||
17 | QString ServerIP; | ||
18 | int Width; | ||
19 | int Height; | ||
20 | int FullScreen; | ||
21 | }; | ||
22 | |||
23 | class 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 | |||
67 | class 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 | |||
83 | class 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 | |||
45 | int g_argc; | ||
46 | char ** g_argv; | ||
47 | |||
48 | char title[32] = ""; | ||
49 | char username[16] = "j"; | ||
50 | char hostname[16] = "sharp"; | ||
51 | char 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 */ | ||
55 | int g_height = 600; | ||
56 | int tcp_port_rdp = TCP_PORT_RDP; | ||
57 | int server_bpp = 8; | ||
58 | int win_button_size = 0;/* If zero, disable single app mode */ | ||
59 | BOOL bitmap_compression = True; | ||
60 | BOOL sendmotion = True; | ||
61 | BOOL orders = True; | ||
62 | BOOL encryption = True; | ||
63 | BOOL desktop_save = True; | ||
64 | BOOL fullscreen = False; | ||
65 | BOOL grab_keyboard = True; | ||
66 | BOOL hide_decorations = False; | ||
67 | extern BOOL owncolmap; | ||
68 | |||
69 | /* report an unimplemented protocol feature */ | ||
70 | void | ||
71 | unimpl(char *format, ...) | ||
72 | { | ||
73 | } | ||
74 | |||
75 | /* malloc; exit if out of memory */ | ||
76 | void * | ||
77 | xmalloc(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 */ | ||
89 | void * | ||
90 | xrealloc(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 */ | ||
102 | void | ||
103 | xfree(void *mem) | ||
104 | { | ||
105 | free(mem); | ||
106 | } | ||
107 | |||
108 | /* report an error */ | ||
109 | void | ||
110 | error(char *format, ...) | ||
111 | { | ||
112 | } | ||
113 | |||
114 | /* report a warning */ | ||
115 | void | ||
116 | warning(char *format, ...) | ||
117 | { | ||
118 | } | ||
119 | |||
120 | /* Generate a 32-byte random for the secure transport code. */ | ||
121 | void | ||
122 | generate_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 | |||
158 | int | ||
159 | load_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 | |||
184 | void | ||
185 | save_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 | |||
23 | extern uint16 mcs_userid; | ||
24 | extern char username[16]; | ||
25 | extern BOOL bitmap_compression; | ||
26 | extern BOOL orders; | ||
27 | extern BOOL encryption; | ||
28 | extern BOOL desktop_save; | ||
29 | |||
30 | uint8 *next_packet; | ||
31 | uint32 rdp_shareid; | ||
32 | |||
33 | /* Initialise an RDP packet */ | ||
34 | static STREAM | ||
35 | rdp_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 */ | ||
46 | static void | ||
47 | rdp_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 */ | ||
62 | STREAM | ||
63 | rdp_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 */ | ||
103 | static STREAM | ||
104 | rdp_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 */ | ||
115 | static void | ||
116 | rdp_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 */ | ||
139 | void | ||
140 | rdp_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 */ | ||
156 | static void | ||
157 | rdp_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 */ | ||
189 | static void | ||
190 | rdp_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 */ | ||
205 | static void | ||
206 | rdp_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 */ | ||
220 | void | ||
221 | rdp_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 */ | ||
241 | static void | ||
242 | rdp_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 */ | ||
258 | static void | ||
259 | rdp_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 */ | ||
277 | static void | ||
278 | rdp_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 */ | ||
298 | static void | ||
299 | rdp_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 */ | ||
337 | static void | ||
338 | rdp_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 */ | ||
353 | static void | ||
354 | rdp_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 */ | ||
366 | static void | ||
367 | rdp_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 */ | ||
379 | static void | ||
380 | rdp_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 */ | ||
390 | static void | ||
391 | rdp_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 */ | ||
401 | static void | ||
402 | rdp_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 | |||
411 | static 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 */ | ||
434 | static void | ||
435 | rdp_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 */ | ||
444 | static void | ||
445 | rdp_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 */ | ||
481 | void | ||
482 | process_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 */ | ||
505 | static void | ||
506 | process_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 */ | ||
551 | static void | ||
552 | process_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 */ | ||
609 | static void | ||
610 | process_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 */ | ||
636 | static void | ||
637 | process_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 */ | ||
667 | void | ||
668 | process_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 */ | ||
700 | BOOL | ||
701 | rdp_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 */ | ||
732 | BOOL | ||
733 | rdp_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 */ | ||
744 | void | ||
745 | rdp_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 | |||
35 | extern char hostname[16]; | ||
36 | extern int g_width; | ||
37 | extern int g_height; | ||
38 | extern int keylayout; | ||
39 | extern BOOL encryption; | ||
40 | extern BOOL licence_issued; | ||
41 | extern int server_bpp; | ||
42 | |||
43 | static int rc4_key_len; | ||
44 | static RC4_KEY rc4_decrypt_key; | ||
45 | static RC4_KEY rc4_encrypt_key; | ||
46 | |||
47 | static uint8 sec_sign_key[16]; | ||
48 | static uint8 sec_decrypt_key[16]; | ||
49 | static uint8 sec_encrypt_key[16]; | ||
50 | static uint8 sec_decrypt_update_key[16]; | ||
51 | static uint8 sec_encrypt_update_key[16]; | ||
52 | static 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 | */ | ||
59 | void | ||
60 | sec_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 | */ | ||
90 | void | ||
91 | sec_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 */ | ||
103 | static void | ||
104 | sec_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 */ | ||
112 | static void | ||
113 | sec_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 | |||
157 | static 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 | |||
164 | static 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) */ | ||
172 | void | ||
173 | buf_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 */ | ||
182 | void | ||
183 | sec_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 */ | ||
210 | static void | ||
211 | sec_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 */ | ||
238 | static void | ||
239 | sec_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 */ | ||
255 | static void | ||
256 | sec_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 | |||
271 | static void | ||
272 | reverse(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 */ | ||
286 | static void | ||
287 | sec_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 */ | ||
322 | STREAM | ||
323 | sec_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 */ | ||
339 | void | ||
340 | sec_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 */ | ||
366 | static void | ||
367 | sec_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 */ | ||
384 | static void | ||
385 | sec_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 */ | ||
454 | static BOOL | ||
455 | sec_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 */ | ||
482 | static BOOL | ||
483 | sec_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 */ | ||
543 | static void | ||
544 | sec_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 */ | ||
560 | static void | ||
561 | sec_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 */ | ||
601 | STREAM | ||
602 | sec_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 */ | ||
633 | BOOL | ||
634 | sec_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 */ | ||
654 | void | ||
655 | sec_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 | |||
36 | static int sock; | ||
37 | static struct stream in; | ||
38 | static struct stream out; | ||
39 | extern int tcp_port_rdp; | ||
40 | |||
41 | /* Initialise TCP transport data packet */ | ||
42 | STREAM | ||
43 | tcp_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 */ | ||
57 | void | ||
58 | tcp_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 */ | ||
81 | STREAM | ||
82 | tcp_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 ∈ | ||
120 | } | ||
121 | |||
122 | /* Establish a connection on the TCP layer */ | ||
123 | BOOL | ||
124 | tcp_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 */ | ||
177 | void | ||
178 | tcp_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 | |||
21 | typedef int BOOL; | ||
22 | |||
23 | #ifndef True | ||
24 | #define True (1) | ||
25 | #define False (0) | ||
26 | #endif | ||
27 | |||
28 | typedef unsigned char uint8; | ||
29 | typedef signed char sint8; | ||
30 | typedef unsigned short uint16; | ||
31 | typedef signed short sint16; | ||
32 | typedef unsigned int uint32; | ||
33 | typedef signed int sint32; | ||
34 | |||
35 | typedef void *HBITMAP; | ||
36 | typedef void *HGLYPH; | ||
37 | typedef void *HCOLOURMAP; | ||
38 | typedef void *HCURSOR; | ||
39 | |||
40 | typedef struct _COLOURENTRY | ||
41 | { | ||
42 | uint8 red; | ||
43 | uint8 green; | ||
44 | uint8 blue; | ||
45 | |||
46 | } | ||
47 | COLOURENTRY; | ||
48 | |||
49 | typedef struct _COLOURMAP | ||
50 | { | ||
51 | uint16 ncolours; | ||
52 | COLOURENTRY *colours; | ||
53 | |||
54 | } | ||
55 | COLOURMAP; | ||
56 | |||
57 | typedef struct _BOUNDS | ||
58 | { | ||
59 | sint16 left; | ||
60 | sint16 top; | ||
61 | sint16 right; | ||
62 | sint16 bottom; | ||
63 | |||
64 | } | ||
65 | BOUNDS; | ||
66 | |||
67 | typedef struct _PEN | ||
68 | { | ||
69 | uint8 style; | ||
70 | uint8 width; | ||
71 | uint32 colour; | ||
72 | |||
73 | } | ||
74 | PEN; | ||
75 | |||
76 | typedef struct _BRUSH | ||
77 | { | ||
78 | uint8 xorigin; | ||
79 | uint8 yorigin; | ||
80 | uint8 style; | ||
81 | uint8 pattern[8]; | ||
82 | |||
83 | } | ||
84 | BRUSH; | ||
85 | |||
86 | typedef struct _FONTGLYPH | ||
87 | { | ||
88 | sint16 offset; | ||
89 | sint16 baseline; | ||
90 | uint16 width; | ||
91 | uint16 height; | ||
92 | HBITMAP pixmap; | ||
93 | |||
94 | } | ||
95 | FONTGLYPH; | ||
96 | |||
97 | typedef struct _DATABLOB | ||
98 | { | ||
99 | void *data; | ||
100 | int size; | ||
101 | |||
102 | } | ||
103 | DATABLOB; | ||
104 | |||
105 | typedef struct _key_translation | ||
106 | { | ||
107 | uint8 scancode; | ||
108 | uint16 modifiers; | ||
109 | } | ||
110 | key_translation; | ||