From 2e4a67200c38c1564555b3c50973f26ae27ed669 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 26 Jul 2013 14:11:44 -0700 Subject: [PATCH] Add constants. More open() implementation. Handle case where no file IDs are available. --- src/protocols/rdp/guac_rdpdr/rdpdr_fs.c | 67 ++++++++++++++----- src/protocols/rdp/guac_rdpdr/rdpdr_fs.h | 44 +++++++++++- src/protocols/rdp/guac_rdpdr/rdpdr_messages.h | 27 ++++++++ src/protocols/rdp/guac_rdpdr/rdpdr_printer.c | 8 +-- 4 files changed, 124 insertions(+), 22 deletions(-) diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c index 05a583bb..ec139175 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c @@ -71,18 +71,11 @@ static void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, Stream_Read_UINT32(input_stream, create_options); Stream_Read_UINT32(input_stream, path_length); + /* Convert path to UTF-8 */ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path, path_length/2 - 1); - path[path_length-1] = 0; /* Open file */ - file_id = guac_rdpdr_fs_open(device); - - /* FIXME: Assuming file IDs are available */ - guac_client_log_info(device->rdpdr->client, "Opened file %s ... new id=%i", path, file_id); - guac_client_log_info(device->rdpdr->client, - "des=%i, attrib=%i, shared=%i, disp=%i, opt=%i", - desired_access, file_attributes, shared_access, create_disposition, - create_options); + file_id = guac_rdpdr_fs_open(device, path); /* Write header */ Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); @@ -91,9 +84,27 @@ static void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, /* Write content */ Stream_Write_UINT32(output_stream, device->device_id); Stream_Write_UINT32(output_stream, completion_id); - Stream_Write_UINT32(output_stream, 0); /* Success */ - Stream_Write_UINT32(output_stream, file_id); /* fileId */ - Stream_Write_UINT8(output_stream, FILE_OPENED); + + /* If no file IDs available, notify server */ + if (file_id == -1) { + guac_client_log_error(device->rdpdr->client, "File open refused - too many open files"); + Stream_Write_UINT32(output_stream, STATUS_TOO_MANY_OPENED_FILES); + Stream_Write_UINT32(output_stream, 0); /* fileId */ + Stream_Write_UINT8(output_stream, 0); /* information */ + } + else { + + guac_client_log_info(device->rdpdr->client, "Opened file \"%s\" ... new id=%i", path, file_id); + guac_client_log_info(device->rdpdr->client, + "des=%i, attrib=%i, shared=%i, disp=%i, opt=%i", + desired_access, file_attributes, shared_access, create_disposition, + create_options); + + Stream_Write_UINT32(output_stream, STATUS_SUCCESS); + Stream_Write_UINT32(output_stream, file_id); /* fileId */ + Stream_Write_UINT8(output_stream, FILE_OPENED); /* information */ + + } svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); @@ -127,7 +138,7 @@ static void guac_rdpdr_fs_process_close(guac_rdpdr_device* device, /* Write content */ Stream_Write_UINT32(output_stream, device->device_id); Stream_Write_UINT32(output_stream, completion_id); - Stream_Write_UINT32(output_stream, 0); /* Success */ + Stream_Write_UINT32(output_stream, STATUS_SUCCESS); Stream_Write(output_stream, "\0\0\0\0\0", 5); /* Padding */ svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); @@ -248,15 +259,31 @@ void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr) { } -int guac_rdpdr_fs_open(guac_rdpdr_device* device) { +int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path) { guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data; + + /* If files available, allocate a new file ID */ if (data->open_files < GUAC_RDPDR_FS_MAX_FILES) { /* Get file ID */ int file_id = guac_pool_next_int(data->file_id_pool); + guac_rdpdr_fs_file* file = &(data->files[file_id]); + data->open_files++; - + + /* If path is empty, it refers to the volume itself */ + if (path[0] == '\0') + file->type = GUAC_RDPDR_FS_VOLUME; + + /* Otherwise, parse path */ + else { + + file->type = GUAC_RDPDR_FS_FILE; + /* STUB */ + + } + return file_id; } @@ -267,8 +294,14 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device) { } void guac_rdpdr_fs_close(guac_rdpdr_device* device, int file_id) { + guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data; - guac_pool_free_int(data->file_id_pool, file_id); - data->open_files--; + + /* Only close if file ID is valid */ + if (file_id >= 0 && file_id <= GUAC_RDPDR_FS_MAX_FILES-1) { + guac_pool_free_int(data->file_id_pool, file_id); + data->open_files--; + } + } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h index a81b6ad6..df1bb8b1 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h @@ -66,6 +66,43 @@ #define FILE_OPENED 0x00000001 #define FILE_OVERWRITTEN 0x00000003 +/** + * Enumeration of all supported file types. + */ +typedef enum guac_rdpdr_fs_file_type { + + /** + * A regular file - either a file or directory. + */ + GUAC_RDPDR_FS_FILE, + + /** + * A disk device - here, this is always virtual, and always the containing + * volume (the Guacamole drive). + */ + GUAC_RDPDR_FS_VOLUME, + +} guac_rdpdr_fs_file_type; + +/** + * An arbitrary file on the virtual filesystem of the Guacamole drive. + */ +typedef struct guac_rdpdr_fs_file { + + /** + * The type of this file - either a FILE (file or directory) or a + * VOLUME (virtual file, represents the virtual device represented by + * the Guacamole drive). + */ + guac_rdpdr_fs_file_type type; + + /** + * Associated local file descriptor. + */ + int fd; + +} guac_rdpdr_fs_file; + /** * Data specific to an instance of the printer device. */ @@ -81,6 +118,11 @@ typedef struct guac_rdpdr_fs_data { */ guac_pool* file_id_pool; + /** + * All available file structures. + */ + guac_rdpdr_fs_file files[GUAC_RDPDR_FS_MAX_FILES]; + } guac_rdpdr_fs_data; /** @@ -92,7 +134,7 @@ void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr); /** * Returns the next available file ID, or -1 if none available. */ -int guac_rdpdr_fs_open(guac_rdpdr_device* device); +int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path); /** * Frees the given file ID, allowing future open operations to reuse it. diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h index 4bb5350a..c3eac7c8 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h @@ -192,6 +192,33 @@ #define IRP_MN_QUERY_DIRECTORY 0x00000001 #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002 +/* + * Status constants. + */ +#define STATUS_SUCCESS 0x00000000 +#define STATUS_DEVICE_OFF_LINE 0x80000010 +#define STATUS_NO_SUCH_FILE 0xC000000F +#define STATUS_END_OF_FILE 0xC0000011 +#define STATUS_FILE_INVALID 0xC0000098 +#define STATUS_FILE_IS_A_DIRECTORY 0xC00000BA +#define STATUS_TOO_MANY_OPENED_FILES 0xC000011F +#define STATUS_CANNOT_DELETE 0xC0000121 +#define STATUS_FILE_DELETED 0xC0000123 +#define STATUS_FILE_CLOSED 0xC0000128 +#define STATUS_FILE_SYSTEM_LIMITATION 0xC0000427 +#define STATUS_FILE_TOO_LARGE 0xC0000904 + +/* + * Volume information constants. + */ + +#define FileFsVolumeInformation 0x00000001 +#define FileFsSizeInformation 0x00000003 +#define FileFsDeviceInformation 0x00000004 +#define FileFsAttributeInformation 0x00000005 +#define FileFsFullSizeInformation 0x00000007 + + /* * Message handlers. */ diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c index 8a0cf189..4bcede11 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c @@ -155,7 +155,7 @@ void guac_rdpdr_process_print_job_create(guac_rdpdr_device* device, /* Write content */ Stream_Write_UINT32(output_stream, device->device_id); Stream_Write_UINT32(output_stream, completion_id); - Stream_Write_UINT32(output_stream, 0); /* Success */ + Stream_Write_UINT32(output_stream, STATUS_SUCCESS); Stream_Write_UINT32(output_stream, 0); /* fileId */ svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); @@ -223,7 +223,7 @@ void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device, /* Start print process */ if (guac_rdpdr_create_print_process(device) != 0) { - status = 0x80000010; + status = STATUS_DEVICE_OFF_LINE; length = 0; } @@ -238,7 +238,7 @@ void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device, length = write(printer_data->printer_input, buffer, length); if (length == -1) { guac_client_log_error(device->rdpdr->client, "Error writing to printer: %s", strerror(errno)); - status = 0x80000010; + status = STATUS_DEVICE_OFF_LINE; length = 0; } @@ -283,7 +283,7 @@ void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device, /* Write content */ Stream_Write_UINT32(output_stream, device->device_id); Stream_Write_UINT32(output_stream, completion_id); - Stream_Write_UINT32(output_stream, 0); /* NTSTATUS - success */ + Stream_Write_UINT32(output_stream, STATUS_SUCCESS); Stream_Write_UINT32(output_stream, 0); /* padding*/ svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream);