freerdp: merge with master
[platform/upstream/freerdp.git] / libfreerdp / core / activation.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
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 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "activation.h"
25
26 /*
27 static const char* const CTRLACTION_STRINGS[] =
28 {
29                 "",
30                 "CTRLACTION_REQUEST_CONTROL",
31                 "CTRLACTION_GRANTED_CONTROL",
32                 "CTRLACTION_DETACH",
33                 "CTRLACTION_COOPERATE"
34 };
35 */
36
37 void rdp_write_synchronize_pdu(wStream* s, rdpSettings* settings)
38 {
39         stream_write_UINT16(s, SYNCMSGTYPE_SYNC); /* messageType (2 bytes) */
40         stream_write_UINT16(s, settings->PduSource); /* targetUser (2 bytes) */
41 }
42
43 BOOL rdp_recv_synchronize_pdu(rdpRdp* rdp, wStream* s)
44 {
45         if (rdp->settings->ServerMode)
46                 return rdp_recv_server_synchronize_pdu(rdp, s);
47         else
48                 return rdp_recv_client_synchronize_pdu(rdp, s);
49 }
50
51 BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s)
52 {
53         rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU;
54         return TRUE;
55 }
56
57 BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
58 {
59         wStream* s;
60
61         s = rdp_data_pdu_init(rdp);
62
63         rdp_write_synchronize_pdu(s, rdp->settings);
64         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id);
65 }
66
67 BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s)
68 {
69         UINT16 messageType;
70
71         rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU;
72
73         if (Stream_GetRemainingLength(s) < 4)
74                 return FALSE;
75
76         stream_read_UINT16(s, messageType); /* messageType (2 bytes) */
77
78         if (messageType != SYNCMSGTYPE_SYNC)
79                 return FALSE;
80
81         /* targetUser (2 bytes) */
82         Stream_Seek_UINT16(s);
83
84         return TRUE;
85 }
86
87 BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp)
88 {
89         wStream* s;
90
91         s = rdp_data_pdu_init(rdp);
92
93         rdp_write_synchronize_pdu(s, rdp->settings);
94
95         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id);
96 }
97
98 BOOL rdp_recv_control_pdu(wStream* s, UINT16* action)
99 {
100         if (Stream_GetRemainingLength(s) < 8)
101                 return FALSE;
102
103         stream_read_UINT16(s, *action); /* action (2 bytes) */
104         Stream_Seek_UINT16(s); /* grantId (2 bytes) */
105         Stream_Seek_UINT32(s); /* controlId (4 bytes) */
106
107         return TRUE;
108 }
109
110 void rdp_write_client_control_pdu(wStream* s, UINT16 action)
111 {
112         stream_write_UINT16(s, action); /* action (2 bytes) */
113         stream_write_UINT16(s, 0); /* grantId (2 bytes) */
114         stream_write_UINT32(s, 0); /* controlId (4 bytes) */
115 }
116
117 BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s)
118 {
119         UINT16 action;
120
121         if(rdp_recv_control_pdu(s, &action) == FALSE)
122                 return FALSE;
123
124         switch (action)
125         {
126                 case CTRLACTION_COOPERATE:
127                         rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_COOPERATE_PDU;
128                         break;
129
130                 case CTRLACTION_GRANTED_CONTROL:
131                         rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_GRANTED_PDU;
132                         rdp->resendFocus = TRUE;
133                         break;
134         }
135
136         return TRUE;
137 }
138
139 BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
140 {
141         wStream* s;
142
143         s = rdp_data_pdu_init(rdp);
144
145         stream_write_UINT16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */
146         stream_write_UINT16(s, 0); /* grantId (2 bytes) */
147         stream_write_UINT32(s, 0); /* controlId (4 bytes) */
148
149         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
150 }
151
152 BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
153 {
154         wStream* s;
155
156         s = rdp_data_pdu_init(rdp);
157
158         stream_write_UINT16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */
159         stream_write_UINT16(s, rdp->mcs->user_id); /* grantId (2 bytes) */
160         stream_write_UINT32(s, 0x03EA); /* controlId (4 bytes) */
161
162         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
163 }
164
165 BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
166 {
167         wStream* 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(wStream* 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(wStream* 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_BYTE(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU); /* bBitMask (1 byte) */
194         stream_write_BYTE(s, 0); /* pad1 (1 byte) */
195         stream_write_UINT16(s, 0); /* pad3 (2 bytes) */
196
197         /* entries */
198 }
199
200 BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
201 {
202         wStream* 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 BOOL rdp_recv_client_font_list_pdu(wStream* s)
211 {
212         if (Stream_GetRemainingLength(s) < 8)
213                 return FALSE;
214
215         return TRUE;
216 }
217
218 void rdp_write_client_font_list_pdu(wStream* 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 BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags)
227 {
228         wStream* 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 BOOL rdp_recv_font_map_pdu(rdpRdp* rdp, wStream* s)
237 {
238         if (rdp->settings->ServerMode)
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 BOOL rdp_recv_server_font_map_pdu(rdpRdp* rdp, wStream* s)
245 {
246         rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU;
247         return TRUE;
248 }
249
250 BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s)
251 {
252         rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU;
253         if(Stream_GetRemainingLength(s) >= 8)
254         {
255                 Stream_Seek_UINT16(s); /* numberEntries (2 bytes) */
256                 Stream_Seek_UINT16(s); /* totalNumEntries (2 bytes) */
257                 Stream_Seek_UINT16(s); /* mapFlags (2 bytes) */
258                 Stream_Seek_UINT16(s); /* entrySize (2 bytes) */
259         }
260
261         return TRUE;
262 }
263
264 BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp)
265 {
266         wStream* s;
267
268         s = rdp_data_pdu_init(rdp);
269
270         stream_write_UINT16(s, 0); /* numberEntries (2 bytes) */
271         stream_write_UINT16(s, 0); /* totalNumEntries (2 bytes) */
272         stream_write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */
273         stream_write_UINT16(s, 4); /* entrySize (2 bytes) */
274
275         return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->user_id);
276 }
277
278 BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
279 {
280         UINT16 lengthSourceDescriptor;
281
282         /*
283          * Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain
284          * the following fields.
285          */
286         if (Stream_GetRemainingLength(s) > 0)
287         {
288                 do {
289                         if(Stream_GetRemainingLength(s) < 4)
290                                 break;
291                         stream_read_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
292                         if(Stream_GetRemainingLength(s) < 2)
293                                 break;
294                         stream_read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
295                         if(Stream_GetRemainingLength(s) < lengthSourceDescriptor)
296                                 break;
297                         Stream_Seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
298                 } while(0);
299         }
300
301         rdp->state = CONNECTION_STATE_CAPABILITY;
302
303         while (rdp->state != CONNECTION_STATE_ACTIVE)
304         {
305                 if (rdp_check_fds(rdp) < 0)
306                         return FALSE;
307                 if (rdp->disconnect)
308                         break;
309         }
310
311         return TRUE;
312 }
313
314 BOOL rdp_send_deactivate_all(rdpRdp* rdp)
315 {
316         wStream* s;
317
318         s = rdp_pdu_init(rdp);
319
320         stream_write_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
321         stream_write_UINT16(s, 1); /* lengthSourceDescriptor (2 bytes) */
322         stream_write_BYTE(s, 0); /* sourceDescriptor (should be 0x00) */
323
324         return rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->user_id);
325 }
326
327 BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s)
328 {
329         UINT16 action;
330
331         if (!rdp_recv_control_pdu(s, &action))
332                 return FALSE;
333         if (action == CTRLACTION_REQUEST_CONTROL)
334         {
335                 if (!rdp_send_server_control_granted_pdu(rdp))
336                         return FALSE;
337         }
338         return TRUE;
339 }
340
341 BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s)
342 {
343         if (!rdp_recv_client_font_list_pdu(s))
344                 return FALSE;
345         if (!rdp_send_server_font_map_pdu(rdp))
346                 return FALSE;
347
348         return TRUE;
349 }
350