rdpdr.h (7285B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#ifndef GUAC_RDP_CHANNELS_RDPDR_H 21#define GUAC_RDP_CHANNELS_RDPDR_H 22 23#include "channels/common-svc.h" 24 25#include <freerdp/freerdp.h> 26#include <guacamole/client.h> 27#include <winpr/stream.h> 28 29#include <stdint.h> 30 31/** 32 * The maximum number of bytes to allow for a device read. 33 */ 34#define GUAC_RDP_MAX_READ_BUFFER 4194304 35 36/** 37 * Arbitrary device forwarded over the RDPDR channel. 38 */ 39typedef struct guac_rdpdr_device guac_rdpdr_device; 40 41/** 42 * The contents of the header common to all RDPDR Device I/O Requests. See: 43 * 44 * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d 45 */ 46typedef struct guac_rdpdr_iorequest { 47 48 /** 49 * The unique ID assigned to the device receiving this I/O request. 50 */ 51 int device_id; 52 53 /** 54 * The unique ID which identifies the relevant file, as returned when the 55 * file was opened. This field may not be relevant to all requests. 56 */ 57 int file_id; 58 59 /** 60 * The unique ID that should be used to refer to this I/O request in future 61 * responses. 62 */ 63 int completion_id; 64 65 /** 66 * Integer ID which identifies the function being requested, such as 67 * IRP_MJ_CREATE (open a file within a shared drive) or IRP_MJ_WRITE (write 68 * data to an open file). 69 */ 70 int major_func; 71 72 /** 73 * Integer ID which identifies a variant of the function denoted by 74 * major_func. This value is only valid for IRP_MJ_DIRECTORY_CONTROL. 75 */ 76 int minor_func; 77 78} guac_rdpdr_iorequest; 79 80/** 81 * Handler for Device I/O Requests. RDPDR devices must provide an 82 * implementation of this function to be able to handle inbound I/O requests. 83 * 84 * @param svc 85 * The guac_rdp_common_svc representing the static virtual channel being 86 * used for RDPDR. 87 * 88 * @param device 89 * The guac_rdpdr_device of the relevant device, as dictated by the 90 * deviceId field of the common RDPDR header within the received PDU. 91 * Within the guac_rdpdr_iorequest structure, the deviceId field is stored 92 * within device_id. 93 * 94 * @param iorequest 95 * The contents of the common RDPDR Device I/O Request header shared by all 96 * RDPDR devices. 97 * 98 * @param input_stream 99 * The remaining data within the received PDU, following the common RDPDR 100 * Device I/O Request header. 101 */ 102typedef void guac_rdpdr_device_iorequest_handler(guac_rdp_common_svc* svc, 103 guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, 104 wStream* input_stream); 105 106/** 107 * Handler for cleaning up the dynamically-allocated portions of a device. 108 * 109 * @param svc 110 * The guac_rdp_common_svc representing the static virtual channel being 111 * used for RDPDR. 112 * 113 * @param device 114 * The guac_rdpdr_device of the device being freed. 115 */ 116typedef void guac_rdpdr_device_free_handler(guac_rdp_common_svc* svc, 117 guac_rdpdr_device* device); 118 119struct guac_rdpdr_device { 120 121 /** 122 * The ID assigned to this device by the RDPDR plugin. 123 */ 124 int device_id; 125 126 /** 127 * Device name, used for logging and for passthrough to the 128 * server. 129 */ 130 const char* device_name; 131 132 /** 133 * The type of RDPDR device that this represents. 134 */ 135 uint32_t device_type; 136 137 /** 138 * The DOS name of the device. Max 8 bytes, including terminator. 139 */ 140 const char *dos_name; 141 142 /** 143 * The stream that stores the RDPDR device announcement for this device. 144 */ 145 wStream* device_announce; 146 147 /** 148 * The length of the device_announce wStream. 149 */ 150 int device_announce_len; 151 152 /** 153 * Handler which should be called for every I/O request received. 154 */ 155 guac_rdpdr_device_iorequest_handler* iorequest_handler; 156 157 /** 158 * Handler which should be called when the device is being freed. 159 */ 160 guac_rdpdr_device_free_handler* free_handler; 161 162 /** 163 * Arbitrary data, used internally by the handlers for this device. 164 */ 165 void* data; 166 167}; 168 169/** 170 * Structure representing the current state of the Guacamole RDPDR plugin for 171 * FreeRDP. 172 */ 173typedef struct guac_rdpdr { 174 175 /** 176 * The number of devices registered within the devices array. 177 */ 178 int devices_registered; 179 180 /** 181 * Array of registered devices. 182 */ 183 guac_rdpdr_device devices[8]; 184 185} guac_rdpdr; 186 187/** 188 * Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header 189 * used for virtually all responses. Depending on the specific I/O completion 190 * being sent, additional space may be reserved within the resulting stream for 191 * additional fields. See: 192 * 193 * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a 194 * 195 * @param device 196 * The device that completed the operation requested by a prior I/O 197 * request. 198 * 199 * @param completion_id 200 * The completion ID of the I/O request that requested the operation. 201 * 202 * @param status 203 * An NTSTATUS code describing the success/failure of the operation that 204 * was completed. 205 * 206 * @param size 207 * The number of additional bytes to reserve at the end of the resulting 208 * stream for additional fields to be appended. 209 * 210 * @return 211 * A new wStream containing an I/O completion header, followed by the 212 * requested additional free space. 213 */ 214wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, 215 int completion_id, int status, int size); 216 217/** 218 * Initializes device redirection support (file transfer, printing, etc.) for 219 * RDP and handling of the RDPDR channel. If failures occur, messages noting 220 * the specifics of those failures will be logged, and the RDP side of 221 * device redirection support will not be functional. 222 * 223 * This MUST be called within the PreConnect callback of the freerdp instance 224 * for RDPDR support to be loaded. 225 * 226 * @param context 227 * The rdpContext associated with the FreeRDP side of the RDP connection. 228 */ 229void guac_rdpdr_load_plugin(rdpContext* context); 230 231/** 232 * Handler which is invoked when the RDPDR channel is connected to the RDP 233 * server. 234 */ 235guac_rdp_common_svc_connect_handler guac_rdpdr_process_connect; 236 237/** 238 * Handler which is invoked when the RDPDR channel has received data from the 239 * RDP server. 240 */ 241guac_rdp_common_svc_receive_handler guac_rdpdr_process_receive; 242 243/** 244 * Handler which is invoked when the RDPDR channel has disconnected and is 245 * about to be freed. 246 */ 247guac_rdp_common_svc_terminate_handler guac_rdpdr_process_terminate; 248 249#endif 250