Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / activation.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * Activation Sequence
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include "activation.h"
21
22 /*
23 static const char* const CTRLACTION_STRINGS[] =
24 {
25                 "",
26                 "CTRLACTION_REQUEST_CONTROL",
27                 "CTRLACTION_GRANTED_CONTROL",
28                 "CTRLACTION_DETACH",
29                 "CTRLACTION_COOPERATE"
30 };
31 */
32
33 void rdp_write_synchronize_pdu(STREAM* s, rdpSettings* settings)
34 {
35         stream_write_uint16(s, SYNCMSGTYPE_SYNC); /* messageType (2 bytes) */
36         stream_write_uint16(s, settings->pdu_source); /* targetUser (2 bytes) */
37 }
38
39 boolean rdp_recv_synchronize_pdu(rdpRdp* rdp, STREAM* s)
40 {
41         if (rdp->settings->server_mode)
42                 return rdp_recv_server_synchronize_pdu(rdp, s);
43         else
44                 return rdp_recv_client_synchronize_pdu(rdp, s);
45 }
46
47 boolean rdp_recv_server_synchronize_pdu(rdpRdp* rdp, STREAM* s)
48 {
49         rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU;
50         return true;
51 }
52
53 boolean rdp_send_server_synchronize_pdu(rdpRdp* rdp)
54 {
55         STREAM* s;
56
57         s = rdp_data_pdu_init(rdp);
58
59         rdp_write_synchronize_pdu(s, rdp->settings);
60         rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id);
61
62         return true;
63 }
64
65 boolean rdp_recv_client_synchronize_pdu(rdpRdp* rdp, STREAM* s)
66 {
67         uint16 messageType;
68
69         rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU;
70
71         if (stream_get_left(s) < 4)
72                 return false;
73
74         stream_read_uint16(s, messageType); /* messageType (2 bytes) */
75
76         if (messageType != SYNCMSGTYPE_SYNC)
77                 return false;
78
79         /* targetUser (2 bytes) */
80         stream_seek_uint16(s);
81
82         return true;
83 }
84
85 boolean rdp_send_client_synchronize_pdu(rdpRdp* rdp)
86 {
87         STREAM* s;
88
89         s = rdp_data_pdu_init(rdp);
90
91         rdp_write_synchronize_pdu(s, rdp->settings);
92
93         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id);
94 }
95
96 boolean rdp_recv_control_pdu(STREAM* s, uint16* action)
97 {
98         if (stream_get_left(s) < 8)
99                 return false;
100
101         stream_read_uint16(s, *action); /* action (2 bytes) */
102         stream_seek_uint16(s); /* grantId (2 bytes) */
103         stream_seek_uint32(s); /* controlId (4 bytes) */
104
105         return true;
106 }
107
108 void rdp_write_client_control_pdu(STREAM* s, uint16 action)
109 {
110         stream_write_uint16(s, action); /* action (2 bytes) */
111         stream_write_uint16(s, 0); /* grantId (2 bytes) */
112         stream_write_uint32(s, 0); /* controlId (4 bytes) */
113 }
114
115 boolean rdp_recv_server_control_pdu(rdpRdp* rdp, STREAM* s)
116 {
117         uint16 action;
118
119         rdp_recv_control_pdu(s, &action);
120
121         switch (action)
122         {
123                 case CTRLACTION_COOPERATE:
124                         rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_COOPERATE_PDU;
125                         break;
126
127                 case CTRLACTION_GRANTED_CONTROL:
128                         rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_GRANTED_PDU;
129                         break;
130         }
131
132         return true;
133 }
134
135 boolean rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
136 {
137         STREAM* s;
138
139         s = rdp_data_pdu_init(rdp);
140
141         stream_write_uint16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */
142         stream_write_uint16(s, 0); /* grantId (2 bytes) */
143         stream_write_uint32(s, 0); /* controlId (4 bytes) */
144
145         rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
146
147         return true;
148 }
149
150 boolean rdp_send_server_control_granted_pdu(rdpRdp* rdp)
151 {
152         STREAM* s;
153
154         s = rdp_data_pdu_init(rdp);
155
156         stream_write_uint16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */
157         stream_write_uint16(s, rdp->mcs->user_id); /* grantId (2 bytes) */
158         stream_write_uint32(s, 0x03EA); /* controlId (4 bytes) */
159
160         rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
161
162         return true;
163 }
164
165 boolean rdp_send_client_control_pdu(rdpRdp* rdp, uint16 action)
166 {
167         STREAM* s;
168
169         s = rdp_data_pdu_init(rdp);
170         rdp_write_client_control_pdu(s, action);
171
172         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
173 }
174
175 void rdp_write_persistent_list_entry(STREAM* s, uint32 key1, uint32 key2)
176 {
177         stream_write_uint32(s, key1); /* key1 (4 bytes) */
178         stream_write_uint32(s, key2); /* key2 (4 bytes) */
179 }
180
181 void rdp_write_client_persistent_key_list_pdu(STREAM* s, rdpSettings* settings)
182 {
183         stream_write_uint16(s, 0); /* numEntriesCache0 (2 bytes) */
184         stream_write_uint16(s, 0); /* numEntriesCache1 (2 bytes) */
185         stream_write_uint16(s, 0); /* numEntriesCache2 (2 bytes) */
186         stream_write_uint16(s, 0); /* numEntriesCache3 (2 bytes) */
187         stream_write_uint16(s, 0); /* numEntriesCache4 (2 bytes) */
188         stream_write_uint16(s, 0); /* totalEntriesCache0 (2 bytes) */
189         stream_write_uint16(s, 0); /* totalEntriesCache1 (2 bytes) */
190         stream_write_uint16(s, 0); /* totalEntriesCache2 (2 bytes) */
191         stream_write_uint16(s, 0); /* totalEntriesCache3 (2 bytes) */
192         stream_write_uint16(s, 0); /* totalEntriesCache4 (2 bytes) */
193         stream_write_uint8(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU); /* bBitMask (1 byte) */
194         stream_write_uint8(s, 0); /* pad1 (1 byte) */
195         stream_write_uint16(s, 0); /* pad3 (2 bytes) */
196
197         /* entries */
198 }
199
200 boolean rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
201 {
202         STREAM* s;
203
204         s = rdp_data_pdu_init(rdp);
205         rdp_write_client_persistent_key_list_pdu(s, rdp->settings);
206
207         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->user_id);
208 }
209
210 boolean rdp_recv_client_font_list_pdu(STREAM* s)
211 {
212         if (stream_get_left(s) < 8)
213                 return false;
214
215         return true;
216 }
217
218 void rdp_write_client_font_list_pdu(STREAM* s, uint16 flags)
219 {
220         stream_write_uint16(s, 0); /* numberFonts (2 bytes) */
221         stream_write_uint16(s, 0); /* totalNumFonts (2 bytes) */
222         stream_write_uint16(s, flags); /* listFlags (2 bytes) */
223         stream_write_uint16(s, 50); /* entrySize (2 bytes) */
224 }
225
226 boolean rdp_send_client_font_list_pdu(rdpRdp* rdp, uint16 flags)
227 {
228         STREAM* s;
229
230         s = rdp_data_pdu_init(rdp);
231         rdp_write_client_font_list_pdu(s, flags);
232
233         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->user_id);
234 }
235
236 boolean rdp_recv_font_map_pdu(rdpRdp* rdp, STREAM* s)
237 {
238         if (rdp->settings->server_mode)
239                 return rdp_recv_server_font_map_pdu(rdp, s);
240         else
241                 return rdp_recv_client_font_map_pdu(rdp, s);
242 }
243
244 boolean rdp_recv_server_font_map_pdu(rdpRdp* rdp, STREAM* s)
245 {
246         rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU;
247         return true;
248 }
249
250 boolean rdp_recv_client_font_map_pdu(rdpRdp* rdp, STREAM* s)
251 {
252         rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU;
253
254         stream_seek_uint16(s); /* numberEntries (2 bytes) */
255         stream_seek_uint16(s); /* totalNumEntries (2 bytes) */
256         stream_seek_uint16(s); /* mapFlags (2 bytes) */
257         stream_seek_uint16(s); /* entrySize (2 bytes) */
258
259         return true;
260 }
261
262 boolean rdp_send_server_font_map_pdu(rdpRdp* rdp)
263 {
264         STREAM* s;
265
266         s = rdp_data_pdu_init(rdp);
267
268         stream_write_uint16(s, 0); /* numberEntries (2 bytes) */
269         stream_write_uint16(s, 0); /* totalNumEntries (2 bytes) */
270         stream_write_uint16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */
271         stream_write_uint16(s, 4); /* entrySize (2 bytes) */
272
273         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->user_id);
274 }
275
276 boolean rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s)
277 {
278         uint16 lengthSourceDescriptor;
279
280         /*
281          * Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain
282          * the following fields.
283          */
284         if (stream_get_left(s) > 0)
285         {
286                 stream_read_uint32(s, rdp->settings->share_id); /* shareId (4 bytes) */
287                 stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
288                 stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
289         }
290
291         rdp->state = CONNECTION_STATE_CAPABILITY;
292
293         while (rdp->state != CONNECTION_STATE_ACTIVE)
294         {
295                 if (rdp_check_fds(rdp) < 0)
296                         return false;
297                 if (rdp->disconnect)
298                         break;
299         }
300
301         return true;
302 }
303
304 boolean rdp_send_deactivate_all(rdpRdp* rdp)
305 {
306         STREAM* s;
307
308         s = rdp_pdu_init(rdp);
309
310         stream_write_uint32(s, rdp->settings->share_id); /* shareId (4 bytes) */
311         stream_write_uint16(s, 1); /* lengthSourceDescriptor (2 bytes) */
312         stream_write_uint8(s, 0); /* sourceDescriptor (should be 0x00) */
313
314         return rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->user_id);
315 }
316
317 boolean rdp_server_accept_client_control_pdu(rdpRdp* rdp, STREAM* s)
318 {
319         uint16 action;
320
321         if (!rdp_recv_control_pdu(s, &action))
322                 return false;
323         if (action == CTRLACTION_REQUEST_CONTROL)
324         {
325                 if (!rdp_send_server_control_granted_pdu(rdp))
326                         return false;
327         }
328         return true;
329 }
330
331 boolean rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, STREAM* s)
332 {
333         if (!rdp_recv_client_font_list_pdu(s))
334                 return false;
335         if (!rdp_send_server_font_map_pdu(rdp))
336                 return false;
337
338         return true;
339 }
340