Fix changelog email address
[freerdp-ubuntu-pcb-backport.git] / channels / rdpdr / rdpdr_capabilities.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol client.
3  * File System Virtual Channel
4  *
5  * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2010-2011 Vic Lee
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <freerdp/utils/stream.h>
26 #include <freerdp/utils/svc_plugin.h>
27
28 #include "rdpdr_types.h"
29 #include "rdpdr_constants.h"
30 #include "rdpdr_capabilities.h"
31
32 /* Output device redirection capability set header */
33 static void rdpdr_write_capset_header(STREAM* data_out, uint16 capabilityType, uint16 capabilityLength, uint32 version)
34 {
35         stream_write_uint16(data_out, capabilityType);
36         stream_write_uint16(data_out, capabilityLength);
37         stream_write_uint32(data_out, version);
38 }
39
40 /* Output device direction general capability set */
41 static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
42 {
43         rdpdr_write_capset_header(data_out, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02);
44
45         stream_write_uint32(data_out, 0); /* osType, ignored on receipt */
46         stream_write_uint32(data_out, 0); /* osVersion, unused and must be set to zero */
47         stream_write_uint16(data_out, 1); /* protocolMajorVersion, must be set to 1 */
48         stream_write_uint16(data_out, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */
49         stream_write_uint32(data_out, 0x0000FFFF); /* ioCode1 */
50         stream_write_uint32(data_out, 0); /* ioCode2, must be set to zero, reserved for future use */
51         stream_write_uint32(data_out, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
52         stream_write_uint32(data_out, ENABLE_ASYNCIO); /* extraFlags1 */
53         stream_write_uint32(data_out, 0); /* extraFlags2, must be set to zero, reserved for future use */
54         stream_write_uint32(data_out, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
55 }
56
57 /* Process device direction general capability set */
58 static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
59 {
60         uint16 capabilityLength;
61
62         stream_read_uint16(data_in, capabilityLength);
63         stream_seek(data_in, capabilityLength - 4);
64 }
65
66 /* Output printer direction capability set */
67 static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
68 {
69         rdpdr_write_capset_header(data_out, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01);
70 }
71
72 /* Process printer direction capability set */
73 static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
74 {
75         uint16 capabilityLength;
76
77         stream_read_uint16(data_in, capabilityLength);
78         stream_seek(data_in, capabilityLength - 4);
79 }
80
81 /* Output port redirection capability set */
82 static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
83 {
84         rdpdr_write_capset_header(data_out, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01);
85 }
86
87 /* Process port redirection capability set */
88 static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
89 {
90         uint16 capabilityLength;
91
92         stream_read_uint16(data_in, capabilityLength);
93         stream_seek(data_in, capabilityLength - 4);
94 }
95
96 /* Output drive redirection capability set */
97 static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
98 {
99         rdpdr_write_capset_header(data_out, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02);
100 }
101
102 /* Process drive redirection capability set */
103 static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
104 {
105         uint16 capabilityLength;
106
107         stream_read_uint16(data_in, capabilityLength);
108         stream_seek(data_in, capabilityLength - 4);
109 }
110
111 /* Output smart card redirection capability set */
112 static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
113 {
114         rdpdr_write_capset_header(data_out, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01);
115 }
116
117 /* Process smartcard redirection capability set */
118 static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
119 {
120         uint16 capabilityLength;
121
122         stream_read_uint16(data_in, capabilityLength);
123         stream_seek(data_in, capabilityLength - 4);
124 }
125
126 void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, STREAM* data_in)
127 {
128         uint16 i;
129         uint16 numCapabilities;
130         uint16 capabilityType;
131
132         stream_read_uint16(data_in, numCapabilities);
133         stream_seek(data_in, 2); /* pad (2 bytes) */
134
135         for(i = 0; i < numCapabilities; i++)
136         {
137                 stream_read_uint16(data_in, capabilityType);
138
139                 switch (capabilityType)
140                 {
141                         case CAP_GENERAL_TYPE:
142                                 rdpdr_process_general_capset(rdpdr, data_in);
143                                 break;
144
145                         case CAP_PRINTER_TYPE:
146                                 rdpdr_process_printer_capset(rdpdr, data_in);
147                                 break;
148
149                         case CAP_PORT_TYPE:
150                                 rdpdr_process_port_capset(rdpdr, data_in);
151                                 break;
152
153                         case CAP_DRIVE_TYPE:
154                                 rdpdr_process_drive_capset(rdpdr, data_in);
155                                 break;
156
157                         case CAP_SMARTCARD_TYPE:
158                                 rdpdr_process_smartcard_capset(rdpdr, data_in);
159                                 break;
160
161                         default:
162                                 DEBUG_WARN("Unknown capabilityType %d", capabilityType);
163                                 break;
164                 }
165         }
166 }
167
168 void rdpdr_send_capability_response(rdpdrPlugin* rdpdr)
169 {
170         STREAM* data_out;
171
172         data_out = stream_new(256);
173
174         stream_write_uint16(data_out, RDPDR_CTYP_CORE);
175         stream_write_uint16(data_out, PAKID_CORE_CLIENT_CAPABILITY);
176
177         stream_write_uint16(data_out, 5); /* numCapabilities */
178         stream_write_uint16(data_out, 0); /* pad */
179
180         rdpdr_write_general_capset(rdpdr, data_out);
181         rdpdr_write_printer_capset(rdpdr, data_out);
182         rdpdr_write_port_capset(rdpdr, data_out);
183         rdpdr_write_drive_capset(rdpdr, data_out);
184         rdpdr_write_smartcard_capset(rdpdr, data_out);
185
186         svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out);
187 }