]> git.sesse.net Git - rdpsrv/blob - rdp.c
11ed6f914d859cfb29c68a716a985375bee64683
[rdpsrv] / rdp.c
1 /* -*- c-basic-offset: 8 -*-
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 <time.h>
22 #include "rdesktop.h"
23
24 extern uint16 g_mcs_userid;
25 extern char g_username[16];
26 extern BOOL g_bitmap_compression;
27 extern BOOL g_orders;
28 BOOL g_encryption = 0;
29 extern BOOL g_desktop_save;
30 extern BOOL g_use_rdp5;
31 extern uint16 g_server_rdp_version;
32 extern int g_server_bpp;
33
34 uint8 *g_next_packet;
35 uint32 g_rdp_shareid;
36
37 #if WITH_DEBUG
38 static uint32 g_packetno;
39 #endif
40
41 /* Receive an RDP packet */
42 STREAM
43 rdp_recv(uint8 * type)
44 {
45         static STREAM rdp_s;
46         uint16 length, pdu_type;
47
48         if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
49         {
50                 rdp_s = sec_recv();
51                 if (rdp_s == NULL)
52                         return NULL;
53
54                 g_next_packet = rdp_s->p;
55         }
56         else
57         {
58                 rdp_s->p = g_next_packet;
59         }
60
61         in_uint16_le(rdp_s, length);
62         /* 32k packets are really 8, keepalive fix */
63         if (length == 0x8000)
64         {
65                 g_next_packet += 8;
66                 *type = 0;
67                 return rdp_s;
68         }
69         in_uint16_le(rdp_s, pdu_type);
70         in_uint8s(rdp_s, 2);    /* userid */
71         *type = pdu_type & 0xf;
72
73 #if WITH_DEBUG
74         DEBUG(("RDP packet #%d, (type %x, length %u)\n", ++g_packetno, *type, length));
75         hexdump(g_next_packet, length);
76 #endif /*  */
77
78         g_next_packet += length;
79         return rdp_s;
80 }
81
82 /* Initialise an RDP data packet */
83 static STREAM
84 rdp_init_data(int maxlen)
85 {
86         STREAM s;
87
88         s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
89         s_push_layer(s, rdp_hdr, 18);
90
91         return s;
92 }
93
94 /* Send an RDP data packet */
95 static void
96 rdp_send_data(STREAM s, uint8 data_pdu_type)
97 {
98         uint16 length;
99
100         s_pop_layer(s, rdp_hdr);
101         length = s->end - s->p;
102
103         out_uint16_le(s, length);
104         out_uint16_le(s, (RDP_PDU_DATA | 0x10));
105         out_uint16_le(s, (g_mcs_userid + 1001));
106
107         out_uint32_le(s, g_rdp_shareid);
108         out_uint8(s, 0);        /* pad */
109         out_uint8(s, 1);        /* streamid */
110         out_uint16_le(s, (length - 14));
111         out_uint8(s, data_pdu_type);
112         out_uint8(s, 0);        /* compress_type */
113         out_uint16(s, 0);       /* compress_len */
114
115         sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
116 }
117
118 /* Output a string in Unicode */
119 void
120 rdp_out_unistr(STREAM s, char *string, int len)
121 {
122         int i = 0, j = 0;
123
124         len += 2;
125
126         while (i < len)
127         {
128                 s->p[i++] = string[j++];
129                 s->p[i++] = 0;
130         }
131
132         s->p += len;
133 }
134
135
136 /* Send a control PDU */
137 static void
138 rdp_send_control(uint16 action)
139 {
140         STREAM s;
141
142         s = rdp_init_data(8);
143
144         out_uint16_le(s, action);
145         out_uint16(s, 0);       /* userid */
146         out_uint32(s, 0);       /* control id */
147
148         s_mark_end(s);
149         rdp_send_data(s, RDP_DATA_PDU_CONTROL);
150 }
151
152 /* Send a synchronisation PDU */
153 static void
154 rdp_send_synchronise(void)
155 {
156         STREAM s;
157
158         s = rdp_init_data(4);
159
160         out_uint16_le(s, 1);    /* type */
161         out_uint16_le(s, 1002);
162
163         s_mark_end(s);
164         rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
165 }
166
167 /* Send a single input event */
168 void
169 rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
170 {
171         STREAM s;
172
173         s = rdp_init_data(16);
174
175         out_uint16_le(s, 1);    /* number of events */
176         out_uint16(s, 0);       /* pad */
177
178         out_uint32_le(s, time);
179         out_uint16_le(s, message_type);
180         out_uint16_le(s, device_flags);
181         out_uint16_le(s, param1);
182         out_uint16_le(s, param2);
183
184         s_mark_end(s);
185         rdp_send_data(s, RDP_DATA_PDU_INPUT);
186 }
187
188 /* Disconnect from the RDP layer */
189 void
190 rdp_disconnect(void)
191 {
192         sec_disconnect();
193 }