cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

rdpdr-fs-messages.c (21821B)


      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#include "channels/common-svc.h"
     21#include "channels/rdpdr/rdpdr-fs-messages-dir-info.h"
     22#include "channels/rdpdr/rdpdr-fs-messages-file-info.h"
     23#include "channels/rdpdr/rdpdr-fs-messages-vol-info.h"
     24#include "channels/rdpdr/rdpdr-fs-messages.h"
     25#include "channels/rdpdr/rdpdr.h"
     26#include "download.h"
     27#include "fs.h"
     28#include "unicode.h"
     29
     30#include <freerdp/channels/rdpdr.h>
     31#include <guacamole/client.h>
     32#include <guacamole/mem.h>
     33#include <winpr/nt.h>
     34#include <winpr/stream.h>
     35#include <winpr/wtypes.h>
     36
     37#include <stdint.h>
     38#include <stdlib.h>
     39#include <string.h>
     40
     41void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
     42        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
     43        wStream* input_stream) {
     44
     45    wStream* output_stream;
     46    int file_id;
     47
     48    int desired_access, file_attributes;
     49    int create_disposition, create_options, path_length;
     50    char path[GUAC_RDP_FS_MAX_PATH];
     51
     52    /* Check remaining stream data prior to reading. */
     53    if (Stream_GetRemainingLength(input_stream) < 32) {
     54        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Create Drive "
     55                "Request PDU does not contain the expected number of bytes. "
     56                "Drive redirection may not work as expected.");
     57        return;
     58    }
     59    
     60    /* Read "create" information */
     61    Stream_Read_UINT32(input_stream, desired_access);
     62    Stream_Seek_UINT64(input_stream); /* allocation size */
     63    Stream_Read_UINT32(input_stream, file_attributes);
     64    Stream_Seek_UINT32(input_stream); /* shared access */
     65    Stream_Read_UINT32(input_stream, create_disposition);
     66    Stream_Read_UINT32(input_stream, create_options);
     67    Stream_Read_UINT32(input_stream, path_length);
     68
     69    /* Check to make sure the stream contains path_length bytes. */
     70    if(Stream_GetRemainingLength(input_stream) < path_length) {
     71        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Create Drive "
     72                "Request PDU does not contain the expected number of bytes. "
     73                "Drive redirection may not work as expected.");
     74        return;
     75    }
     76    
     77    /* Convert path to UTF-8 */
     78    guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1,
     79            path, sizeof(path));
     80
     81    /* Open file */
     82    file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, path,
     83            desired_access, file_attributes,
     84            create_disposition, create_options);
     85
     86    guac_client_log(svc->client, GUAC_LOG_DEBUG,
     87            "%s: [file_id=%i] "
     88             "desired_access=0x%x, file_attributes=0x%x, "
     89             "create_disposition=0x%x, create_options=0x%x, path=\"%s\"",
     90             __func__, file_id,
     91             desired_access, file_attributes,
     92             create_disposition, create_options, path);
     93
     94    /* If an error occurred, notify server */
     95    if (file_id < 0) {
     96        guac_client_log(svc->client, GUAC_LOG_ERROR,
     97                "File open refused (%i): \"%s\"", file_id, path);
     98
     99        output_stream = guac_rdpdr_new_io_completion(device,
    100                iorequest->completion_id, guac_rdp_fs_get_status(file_id), 5);
    101        Stream_Write_UINT32(output_stream, 0); /* fileId */
    102        Stream_Write_UINT8(output_stream,  0); /* information */
    103    }
    104
    105    /* Otherwise, open succeeded */
    106    else {
    107
    108        guac_rdp_fs_file* file;
    109
    110        output_stream = guac_rdpdr_new_io_completion(device,
    111                iorequest->completion_id, STATUS_SUCCESS, 5);
    112        Stream_Write_UINT32(output_stream, file_id);    /* fileId */
    113        Stream_Write_UINT8(output_stream,  0);          /* information */
    114
    115        /* Create \Download if it doesn't exist */
    116        file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
    117        if (file != NULL && strcmp(file->absolute_path, "\\") == 0) {
    118            
    119            /* Only create Download folder if downloads are enabled. */
    120            if (!((guac_rdp_fs*) device->data)->disable_download) {
    121                int download_id =
    122                    guac_rdp_fs_open((guac_rdp_fs*) device->data, "\\Download",
    123                        GENERIC_READ, 0, FILE_OPEN_IF, FILE_DIRECTORY_FILE);
    124                
    125                if (download_id >= 0)
    126                    guac_rdp_fs_close((guac_rdp_fs*) device->data, download_id);
    127            }
    128
    129        }
    130
    131    }
    132
    133    guac_rdp_common_svc_write(svc, output_stream);
    134
    135}
    136
    137void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
    138        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    139        wStream* input_stream) {
    140
    141    UINT32 length;
    142    UINT64 offset;
    143    char* buffer;
    144    int bytes_read;
    145
    146    wStream* output_stream;
    147
    148    /* Check remaining bytes before reading stream. */
    149    if (Stream_GetRemainingLength(input_stream) < 12) {
    150        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Read "
    151                "Request PDU does not contain the expected number of bytes. "
    152                "Drive redirection may not work as expected.");
    153        return;
    154    }
    155    
    156    /* Read packet */
    157    Stream_Read_UINT32(input_stream, length);
    158    Stream_Read_UINT64(input_stream, offset);
    159
    160    guac_client_log(svc->client, GUAC_LOG_DEBUG,
    161            "%s: [file_id=%i] length=%i, offset=%" PRIu64,
    162             __func__, iorequest->file_id, length, (uint64_t) offset);
    163
    164    /* Ensure buffer size does not exceed a safe maximum */
    165    if (length > GUAC_RDP_MAX_READ_BUFFER)
    166        length = GUAC_RDP_MAX_READ_BUFFER;
    167
    168    /* Allocate buffer */
    169    buffer = guac_mem_alloc(length);
    170
    171    /* Attempt read */
    172    bytes_read = guac_rdp_fs_read((guac_rdp_fs*) device->data,
    173            iorequest->file_id, offset, buffer, length);
    174
    175    /* If error, return invalid parameter */
    176    if (bytes_read < 0) {
    177        output_stream = guac_rdpdr_new_io_completion(device,
    178                iorequest->completion_id, guac_rdp_fs_get_status(bytes_read), 4);
    179        Stream_Write_UINT32(output_stream, 0); /* Length */
    180    }
    181
    182    /* Otherwise, send bytes read */
    183    else {
    184        output_stream = guac_rdpdr_new_io_completion(device,
    185                iorequest->completion_id, STATUS_SUCCESS, 4+bytes_read);
    186        Stream_Write_UINT32(output_stream, bytes_read);  /* Length */
    187        Stream_Write(output_stream, buffer, bytes_read); /* ReadData */
    188    }
    189
    190    guac_rdp_common_svc_write(svc, output_stream);
    191    guac_mem_free(buffer);
    192
    193}
    194
    195void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
    196        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    197        wStream* input_stream) {
    198
    199    UINT32 length;
    200    UINT64 offset;
    201    int bytes_written;
    202
    203    wStream* output_stream;
    204
    205    /* Check remaining length. */
    206    if (Stream_GetRemainingLength(input_stream) < 32) {
    207        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Write "
    208                "Request PDU does not contain the expected number of bytes. "
    209                "Drive redirection may not work as expected.");
    210        return;
    211    }
    212    
    213    /* Read packet */
    214    Stream_Read_UINT32(input_stream, length);
    215    Stream_Read_UINT64(input_stream, offset);
    216    Stream_Seek(input_stream, 20); /* Padding */
    217
    218    guac_client_log(svc->client, GUAC_LOG_DEBUG,
    219            "%s: [file_id=%i] length=%i, offset=%" PRIu64,
    220             __func__, iorequest->file_id, length, (uint64_t) offset);
    221
    222    /* Check to make sure stream contains at least length bytes */
    223    if (Stream_GetRemainingLength(input_stream) < length) {
    224        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Write "
    225                "Request PDU does not contain the expected number of bytes. "
    226                "Drive redirection may not work as expected.");
    227        return;
    228    }
    229    
    230    /* Attempt write */
    231    bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data,
    232            iorequest->file_id, offset, Stream_Pointer(input_stream), length);
    233
    234    /* If error, return invalid parameter */
    235    if (bytes_written < 0) {
    236        output_stream = guac_rdpdr_new_io_completion(device,
    237                iorequest->completion_id, guac_rdp_fs_get_status(bytes_written), 5);
    238        Stream_Write_UINT32(output_stream, 0); /* Length */
    239        Stream_Write_UINT8(output_stream, 0);  /* Padding */
    240    }
    241
    242    /* Otherwise, send success */
    243    else {
    244        output_stream = guac_rdpdr_new_io_completion(device,
    245                iorequest->completion_id, STATUS_SUCCESS, 5);
    246        Stream_Write_UINT32(output_stream, bytes_written); /* Length */
    247        Stream_Write_UINT8(output_stream, 0);              /* Padding */
    248    }
    249
    250    guac_rdp_common_svc_write(svc, output_stream);
    251
    252}
    253
    254void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc,
    255        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    256        wStream* input_stream) {
    257
    258    wStream* output_stream;
    259    guac_rdp_fs_file* file;
    260
    261    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]",
    262            __func__, iorequest->file_id);
    263
    264    /* Get file */
    265    file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
    266    if (file == NULL)
    267        return;
    268
    269    /* If file was written to, and it's in the \Download folder, start stream */
    270    if (file->bytes_written > 0
    271            && strncmp(file->absolute_path, "\\Download\\", 10) == 0
    272			&& !((guac_rdp_fs*) device->data)->disable_download) {
    273        guac_client_for_owner(svc->client, guac_rdp_download_to_user, file->absolute_path);
    274        guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id);
    275    }
    276
    277    /* Close file */
    278    guac_rdp_fs_close((guac_rdp_fs*) device->data, iorequest->file_id);
    279
    280    output_stream = guac_rdpdr_new_io_completion(device,
    281            iorequest->completion_id, STATUS_SUCCESS, 4);
    282    Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */
    283
    284    guac_rdp_common_svc_write(svc, output_stream);
    285
    286}
    287
    288void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc,
    289        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    290        wStream* input_stream) {
    291
    292    int fs_information_class;
    293
    294    /* Check remaining length */
    295    if (Stream_GetRemainingLength(input_stream) < 4) {
    296        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
    297                "Volume Information PDU does not contain the expected number "
    298                "of bytes. Drive redirection may not work as expected.");
    299        return;
    300    }
    301    
    302    Stream_Read_UINT32(input_stream, fs_information_class);
    303
    304    /* Dispatch to appropriate class-specific handler */
    305    switch (fs_information_class) {
    306
    307        case FileFsVolumeInformation:
    308            guac_rdpdr_fs_process_query_volume_info(svc, device, iorequest, input_stream);
    309            break;
    310
    311        case FileFsSizeInformation:
    312            guac_rdpdr_fs_process_query_size_info(svc, device, iorequest, input_stream);
    313            break;
    314
    315        case FileFsDeviceInformation:
    316            guac_rdpdr_fs_process_query_device_info(svc, device, iorequest, input_stream);
    317            break;
    318
    319        case FileFsAttributeInformation:
    320            guac_rdpdr_fs_process_query_attribute_info(svc, device, iorequest, input_stream);
    321            break;
    322
    323        case FileFsFullSizeInformation:
    324            guac_rdpdr_fs_process_query_full_size_info(svc, device, iorequest, input_stream);
    325            break;
    326
    327        default:
    328            guac_client_log(svc->client, GUAC_LOG_DEBUG,
    329                    "Unknown volume information class: 0x%x", fs_information_class);
    330    }
    331
    332}
    333
    334void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc,
    335        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    336        wStream* input_stream) {
    337
    338    int fs_information_class;
    339
    340    /* Check remaining length */
    341    if (Stream_GetRemainingLength(input_stream) < 4) {
    342        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
    343                "Information PDU does not contain the expected number of "
    344                "bytes. Drive redirection may not work as expected.");
    345        return;
    346    }
    347    
    348    Stream_Read_UINT32(input_stream, fs_information_class);
    349
    350    /* Dispatch to appropriate class-specific handler */
    351    switch (fs_information_class) {
    352
    353        case FileBasicInformation:
    354            guac_rdpdr_fs_process_query_basic_info(svc, device, iorequest, input_stream);
    355            break;
    356
    357        case FileStandardInformation:
    358            guac_rdpdr_fs_process_query_standard_info(svc, device, iorequest, input_stream);
    359            break;
    360
    361        case FileAttributeTagInformation:
    362            guac_rdpdr_fs_process_query_attribute_tag_info(svc, device, iorequest, input_stream);
    363            break;
    364
    365        default:
    366            guac_client_log(svc->client, GUAC_LOG_DEBUG,
    367                    "Unknown file information class: 0x%x", fs_information_class);
    368    }
    369
    370}
    371
    372void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc,
    373        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    374        wStream* input_stream) {
    375
    376    wStream* output_stream = guac_rdpdr_new_io_completion(device,
    377            iorequest->completion_id, STATUS_NOT_SUPPORTED, 0);
    378
    379    guac_client_log(svc->client, GUAC_LOG_DEBUG,
    380            "%s: [file_id=%i] Set volume info not supported",
    381            __func__, iorequest->file_id);
    382
    383    guac_rdp_common_svc_write(svc, output_stream);
    384
    385}
    386
    387void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc,
    388        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    389        wStream* input_stream) {
    390
    391    int fs_information_class;
    392    int length;
    393
    394    /* Check remaining length */
    395    if (Stream_GetRemainingLength(input_stream) < 32) {
    396        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
    397                "Information PDU does not contain the expected number of "
    398                "bytes. Drive redirection may not work as expected.");
    399        return;
    400    }
    401    
    402    Stream_Read_UINT32(input_stream, fs_information_class);
    403    Stream_Read_UINT32(input_stream, length); /* Length */
    404    Stream_Seek(input_stream, 24);            /* Padding */
    405
    406    /* Dispatch to appropriate class-specific handler */
    407    switch (fs_information_class) {
    408
    409        case FileBasicInformation:
    410            guac_rdpdr_fs_process_set_basic_info(svc, device, iorequest, length, input_stream);
    411            break;
    412
    413        case FileEndOfFileInformation:
    414            guac_rdpdr_fs_process_set_end_of_file_info(svc, device, iorequest, length, input_stream);
    415            break;
    416
    417        case FileDispositionInformation:
    418            guac_rdpdr_fs_process_set_disposition_info(svc, device, iorequest, length, input_stream);
    419            break;
    420
    421        case FileRenameInformation:
    422            guac_rdpdr_fs_process_set_rename_info(svc, device, iorequest, length, input_stream);
    423            break;
    424
    425        case FileAllocationInformation:
    426            guac_rdpdr_fs_process_set_allocation_info(svc, device, iorequest, length, input_stream);
    427            break;
    428
    429        default:
    430            guac_client_log(svc->client, GUAC_LOG_DEBUG,
    431                    "Unknown file information class: 0x%x",
    432                    fs_information_class);
    433    }
    434
    435}
    436
    437void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc,
    438        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    439        wStream* input_stream) {
    440
    441    wStream* output_stream = guac_rdpdr_new_io_completion(device,
    442            iorequest->completion_id, STATUS_INVALID_PARAMETER, 4);
    443
    444    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED",
    445            __func__, iorequest->file_id);
    446
    447    /* No content for now */
    448    Stream_Write_UINT32(output_stream, 0);
    449
    450    guac_rdp_common_svc_write(svc, output_stream);
    451
    452}
    453
    454void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc,
    455        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    456        wStream* input_stream) {
    457
    458    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Not "
    459            "implemented", __func__, iorequest->file_id);
    460
    461}
    462
    463void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
    464        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    465        wStream* input_stream) {
    466
    467    wStream* output_stream;
    468
    469    guac_rdp_fs_file* file;
    470    int fs_information_class, initial_query;
    471    int path_length;
    472
    473    const char* entry_name;
    474
    475    /* Get file */
    476    file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
    477    if (file == NULL)
    478        return;
    479
    480    if (Stream_GetRemainingLength(input_stream) < 9) {
    481        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
    482                "Directory PDU does not contain the expected number of bytes. "
    483                "Drive redirection may not work as expected.");
    484        return;
    485    }
    486    
    487    /* Read main header */
    488    Stream_Read_UINT32(input_stream, fs_information_class);
    489    Stream_Read_UINT8(input_stream,  initial_query);
    490    Stream_Read_UINT32(input_stream, path_length);
    491
    492    /* If this is the first query, the path is included after padding */
    493    if (initial_query) {
    494
    495        /*
    496         * Check to make sure Stream has at least the 23 padding bytes in it
    497         * prior to seeking.
    498         */
    499        if (Stream_GetRemainingLength(input_stream) < (23 + path_length)) {
    500            guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
    501                    "Directory PDU does not contain the expected number of "
    502                    "bytes. Drive redirection may not work as expected.");
    503            return;
    504        }
    505        
    506        Stream_Seek(input_stream, 23);       /* Padding */
    507        
    508        /* Convert path to UTF-8 */
    509        guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1,
    510                file->dir_pattern, sizeof(file->dir_pattern));
    511
    512    }
    513
    514    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] "
    515            "initial_query=%i, dir_pattern=\"%s\"", __func__,
    516            iorequest->file_id, initial_query, file->dir_pattern);
    517
    518    /* Find first matching entry in directory */
    519    while ((entry_name = guac_rdp_fs_read_dir((guac_rdp_fs*) device->data,
    520                    iorequest->file_id)) != NULL) {
    521
    522        /* Convert to absolute path */
    523        char entry_path[GUAC_RDP_FS_MAX_PATH];
    524        if (guac_rdp_fs_convert_path(file->absolute_path,
    525                    entry_name, entry_path) == 0) {
    526
    527            int entry_file_id;
    528
    529            /* Pattern defined and match fails, continue with next file */
    530            if (guac_rdp_fs_matches(entry_path, file->dir_pattern))
    531                continue;
    532
    533            /* Open directory entry */
    534            entry_file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data,
    535                    entry_path, FILE_READ_DATA, 0, FILE_OPEN, 0);
    536
    537            if (entry_file_id >= 0) {
    538
    539                /* Dispatch to appropriate class-specific handler */
    540                switch (fs_information_class) {
    541
    542                    case FileDirectoryInformation:
    543                        guac_rdpdr_fs_process_query_directory_info(svc, device,
    544                                iorequest, entry_name, entry_file_id);
    545                        break;
    546
    547                    case FileFullDirectoryInformation:
    548                        guac_rdpdr_fs_process_query_full_directory_info(svc,
    549                                device, iorequest, entry_name, entry_file_id);
    550                        break;
    551
    552                    case FileBothDirectoryInformation:
    553                        guac_rdpdr_fs_process_query_both_directory_info(svc,
    554                                device, iorequest, entry_name, entry_file_id);
    555                        break;
    556
    557                    case FileNamesInformation:
    558                        guac_rdpdr_fs_process_query_names_info(svc, device,
    559                                iorequest, entry_name, entry_file_id);
    560                        break;
    561
    562                    default:
    563                        guac_client_log(svc->client, GUAC_LOG_DEBUG,
    564                                "Unknown dir information class: 0x%x",
    565                                fs_information_class);
    566                }
    567
    568                guac_rdp_fs_close((guac_rdp_fs*) device->data, entry_file_id);
    569                return;
    570
    571            } /* end if file exists */
    572        } /* end if path valid */
    573    } /* end if entry exists */
    574
    575    /*
    576     * Handle errors as a lack of files.
    577     */
    578
    579    output_stream = guac_rdpdr_new_io_completion(device,
    580            iorequest->completion_id, STATUS_NO_MORE_FILES, 5);
    581
    582    Stream_Write_UINT32(output_stream, 0); /* Length */
    583    Stream_Write_UINT8(output_stream, 0);  /* Padding */
    584
    585    guac_rdp_common_svc_write(svc, output_stream);
    586
    587}
    588
    589void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc,
    590        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    591        wStream* input_stream) {
    592
    593    wStream* output_stream = guac_rdpdr_new_io_completion(device,
    594            iorequest->completion_id, STATUS_NOT_SUPPORTED, 5);
    595
    596    guac_client_log(svc->client, GUAC_LOG_DEBUG,
    597            "%s: [file_id=%i] Lock not supported",
    598            __func__, iorequest->file_id);
    599
    600    Stream_Zero(output_stream, 5); /* Padding */
    601
    602    guac_rdp_common_svc_write(svc, output_stream);
    603
    604}
    605