GUACAMOLE-249: Refactor RDPDR to be more documentable. Document RDPDR fully.
This commit is contained in:
parent
36545cc92c
commit
d2083a1aed
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "channels/rdpdr/rdpdr-fs-messages-dir-info.h"
|
||||
#include "channels/rdpdr/rdpdr.h"
|
||||
#include "fs.h"
|
||||
#include "unicode.h"
|
||||
@ -29,8 +30,8 @@
|
||||
#include <stddef.h>
|
||||
|
||||
void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
const char* entry_name, int entry_file_id) {
|
||||
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
@ -43,16 +44,17 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc,
|
||||
(char*) utf16_entry_name, sizeof(utf16_entry_name));
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i (entry_name=\"%s\")]",
|
||||
__func__, file_id, entry_name);
|
||||
__func__, entry_file_id, entry_name);
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 4 + 64 + utf16_length + 2);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS,
|
||||
4 + 64 + utf16_length + 2);
|
||||
|
||||
Stream_Write_UINT32(output_stream,
|
||||
64 + utf16_length + 2); /* Length */
|
||||
@ -76,8 +78,8 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
const char* entry_name, int entry_file_id) {
|
||||
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
@ -90,16 +92,17 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc,
|
||||
(char*) utf16_entry_name, sizeof(utf16_entry_name));
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i (entry_name=\"%s\")]",
|
||||
__func__, file_id, entry_name);
|
||||
__func__, entry_file_id, entry_name);
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 4 + 68 + utf16_length + 2);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS,
|
||||
4 + 68 + utf16_length + 2);
|
||||
|
||||
Stream_Write_UINT32(output_stream,
|
||||
68 + utf16_length + 2); /* Length */
|
||||
@ -124,8 +127,8 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
const char* entry_name, int entry_file_id) {
|
||||
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
@ -138,16 +141,17 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc,
|
||||
(char*) utf16_entry_name, sizeof(utf16_entry_name));
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i (entry_name=\"%s\")]",
|
||||
__func__, file_id, entry_name);
|
||||
__func__, entry_file_id, entry_name);
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 4 + 69 + 24 + utf16_length + 2);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS,
|
||||
4 + 69 + 24 + utf16_length + 2);
|
||||
|
||||
Stream_Write_UINT32(output_stream,
|
||||
69 + 24 + utf16_length + 2); /* Length */
|
||||
@ -176,8 +180,8 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
const char* entry_name, int entry_file_id) {
|
||||
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
@ -190,16 +194,17 @@ void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc,
|
||||
(char*) utf16_entry_name, sizeof(utf16_entry_name));
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i (entry_name=\"%s\")]",
|
||||
__func__, file_id, entry_name);
|
||||
__func__, entry_file_id, entry_name);
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 4 + 12 + utf16_length + 2);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS,
|
||||
4 + 12 + utf16_length + 2);
|
||||
|
||||
Stream_Write_UINT32(output_stream,
|
||||
12 + utf16_length + 2); /* Length */
|
||||
|
@ -34,40 +34,60 @@
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/**
|
||||
* Handler for Device I/O Requests which query information about the files
|
||||
* within a directory.
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*
|
||||
* @param device
|
||||
* The guac_rdpdr_device of the relevant device, as dictated by the
|
||||
* deviceId field of common RDPDR header within the received PDU. Within
|
||||
* the guac_rdpdr_iorequest structure, the deviceId field is stored within
|
||||
* device_id.
|
||||
*
|
||||
* @param iorequest
|
||||
* The contents of the common RDPDR Device I/O Request header shared by all
|
||||
* RDPDR devices.
|
||||
*
|
||||
* @param entry_name
|
||||
* The filename of the file being queried.
|
||||
*
|
||||
* @param entry_file_id
|
||||
* The ID of the file being queried.
|
||||
*/
|
||||
typedef void guac_rdpdr_directory_query_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
const char* entry_name, int entry_file_id);
|
||||
|
||||
/**
|
||||
* Processes a query request for FileDirectoryInformation. From the
|
||||
* documentation this is "defined as the file's name, time stamp, and size, or its
|
||||
* attributes."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_directory_info;
|
||||
|
||||
/**
|
||||
* Processes a query request for FileFullDirectoryInformation. From the
|
||||
* documentation, this is "defined as all the basic information, plus extended
|
||||
* attribute size."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_full_directory_info;
|
||||
|
||||
/**
|
||||
* Processes a query request for FileBothDirectoryInformation. From the
|
||||
* documentation, this absurdly-named request is "basic information plus
|
||||
* extended attribute size and short name about a file or directory."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_both_directory_info;
|
||||
|
||||
/**
|
||||
* Processes a query request for FileNamesInformation. From the documentation,
|
||||
* this is "detailed information on the names of files in a directory."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_names_info;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "channels/rdpdr/rdpdr-fs-messages-file-info.h"
|
||||
#include "channels/rdpdr/rdpdr.h"
|
||||
#include "fs.h"
|
||||
#include "unicode.h"
|
||||
@ -31,23 +32,22 @@
|
||||
#include <string.h>
|
||||
|
||||
void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream;
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 40);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS, 40);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 36);
|
||||
Stream_Write_UINT64(output_stream, file->ctime); /* CreationTime */
|
||||
@ -63,27 +63,26 @@ void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream;
|
||||
guac_rdp_fs_file* file;
|
||||
BOOL is_directory = FALSE;
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
if (file->attributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
is_directory = TRUE;
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 26);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS, 26);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 22);
|
||||
Stream_Write_UINT64(output_stream, file->size); /* AllocationSize */
|
||||
@ -99,23 +98,22 @@ void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream;
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 12);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS, 12);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 8);
|
||||
Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */
|
||||
@ -128,8 +126,8 @@ void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
int length, wStream* input_stream) {
|
||||
|
||||
int result;
|
||||
int filename_length;
|
||||
@ -145,9 +143,9 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
|
||||
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2,
|
||||
destination_path, sizeof(destination_path));
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] destination_path=\"%s\"",
|
||||
__func__, file_id, destination_path);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]"
|
||||
"destination_path=\"%s\"", __func__, iorequest->file_id,
|
||||
destination_path);
|
||||
|
||||
/* If file moving to \Download folder, start stream, do not move */
|
||||
if (strncmp(destination_path, "\\Download\\", 10) == 0) {
|
||||
@ -155,28 +153,28 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
/* Initiate download, pretend move succeeded */
|
||||
guac_rdpdr_start_download(svc, device, file->absolute_path);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 4);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
|
||||
}
|
||||
|
||||
/* Otherwise, rename as requested */
|
||||
else {
|
||||
|
||||
result = guac_rdp_fs_rename((guac_rdp_fs*) device->data, file_id,
|
||||
destination_path);
|
||||
result = guac_rdp_fs_rename((guac_rdp_fs*) device->data,
|
||||
iorequest->file_id, destination_path);
|
||||
if (result < 0)
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, guac_rdp_fs_get_status(result), 4);
|
||||
iorequest->completion_id, guac_rdp_fs_get_status(result), 4);
|
||||
else
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 4);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
|
||||
}
|
||||
|
||||
@ -186,8 +184,8 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
int length, wStream* input_stream) {
|
||||
|
||||
int result;
|
||||
UINT64 size;
|
||||
@ -196,18 +194,17 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc,
|
||||
/* Read new size */
|
||||
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] size=%" PRIu64,
|
||||
__func__, file_id, (uint64_t) size);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] "
|
||||
"size=%" PRIu64, __func__, iorequest->file_id, (uint64_t) size);
|
||||
|
||||
/* Truncate file */
|
||||
result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, file_id, size);
|
||||
result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, iorequest->file_id, size);
|
||||
if (result < 0)
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, guac_rdp_fs_get_status(result), 4);
|
||||
iorequest->completion_id, guac_rdp_fs_get_status(result), 4);
|
||||
else
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 4);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
|
||||
Stream_Write_UINT32(output_stream, length);
|
||||
guac_rdp_common_svc_write(svc, output_stream);
|
||||
@ -215,23 +212,22 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
int length, wStream* input_stream) {
|
||||
|
||||
wStream* output_stream;
|
||||
|
||||
/* Delete file */
|
||||
int result = guac_rdp_fs_delete((guac_rdp_fs*) device->data, file_id);
|
||||
int result = guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
if (result < 0)
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, guac_rdp_fs_get_status(result), 4);
|
||||
iorequest->completion_id, guac_rdp_fs_get_status(result), 4);
|
||||
else
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 4);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
Stream_Write_UINT32(output_stream, length);
|
||||
|
||||
@ -240,8 +236,8 @@ void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
int length, wStream* input_stream) {
|
||||
|
||||
int result;
|
||||
UINT64 size;
|
||||
@ -250,18 +246,17 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc,
|
||||
/* Read new size */
|
||||
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] size=%" PRIu64,
|
||||
__func__, file_id, (uint64_t) size);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] "
|
||||
"size=%" PRIu64, __func__, iorequest->file_id, (uint64_t) size);
|
||||
|
||||
/* Truncate file */
|
||||
result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, file_id, size);
|
||||
result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, iorequest->file_id, size);
|
||||
if (result < 0)
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, guac_rdp_fs_get_status(result), 4);
|
||||
iorequest->completion_id, guac_rdp_fs_get_status(result), 4);
|
||||
else
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 4);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
|
||||
Stream_Write_UINT32(output_stream, length);
|
||||
guac_rdp_common_svc_write(svc, output_stream);
|
||||
@ -269,18 +264,17 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
int length, wStream* input_stream) {
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 4);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
|
||||
/* Currently do nothing, just respond */
|
||||
Stream_Write_UINT32(output_stream, length);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] IGNORED",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED",
|
||||
__func__, iorequest->file_id);
|
||||
|
||||
guac_rdp_common_svc_write(svc, output_stream);
|
||||
|
||||
|
@ -33,72 +33,88 @@
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/**
|
||||
* Handler for Device I/O Requests which set/update file information.
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*
|
||||
* @param device
|
||||
* The guac_rdpdr_device of the relevant device, as dictated by the
|
||||
* deviceId field of common RDPDR header within the received PDU. Within
|
||||
* the guac_rdpdr_iorequest structure, the deviceId field is stored within
|
||||
* device_id.
|
||||
*
|
||||
* @param iorequest
|
||||
* The contents of the common RDPDR Device I/O Request header shared by all
|
||||
* RDPDR devices.
|
||||
*
|
||||
* @param length
|
||||
* The length of the SetBuffer field of the I/O request, in bytes. Whether
|
||||
* the SetBuffer field is applicable to a particular request, as well as
|
||||
* the specific contents of that field, depend on the type of request.
|
||||
*
|
||||
* @param input_stream
|
||||
* The remaining data within the received PDU, following the common RDPDR
|
||||
* Device I/O Request header and length field. If the SetBuffer field is
|
||||
* used for this request, the first byte of SetBuffer will be the first
|
||||
* byte read from this stream.
|
||||
*/
|
||||
typedef void guac_rdpdr_set_information_request_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
int length, wStream* input_stream);
|
||||
|
||||
/**
|
||||
* Processes a query for FileBasicInformation. From the documentation, this is
|
||||
* "used to query a file for the times of creation, last access, last write,
|
||||
* and change, in addition to file attribute information."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_basic_info;
|
||||
|
||||
/**
|
||||
* Processes a query for FileStandardInformation. From the documentation, this
|
||||
* is "used to query for file information such as allocation size, end-of-file
|
||||
* position, and number of links."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_standard_info;
|
||||
|
||||
/**
|
||||
* Processes a query for FileAttributeTagInformation. From the documentation
|
||||
* this is "used to query for file attribute and reparse tag information."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_attribute_tag_info;
|
||||
|
||||
/**
|
||||
* Process a set operation for FileRenameInformation. From the documentation,
|
||||
* this operation is used to rename a file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length);
|
||||
guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_rename_info;
|
||||
|
||||
/**
|
||||
* Process a set operation for FileAllocationInformation. From the
|
||||
* documentation, this operation is used to set a file's allocation size.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length);
|
||||
guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_allocation_info;
|
||||
|
||||
/**
|
||||
* Process a set operation for FileDispositionInformation. From the
|
||||
* documentation, this operation is used to mark a file for deletion.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length);
|
||||
guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_disposition_info;
|
||||
|
||||
/**
|
||||
* Process a set operation for FileEndOfFileInformation. From the
|
||||
* documentation, this operation is used "to set end-of-file information for
|
||||
* a file."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length);
|
||||
guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_end_of_file_info;
|
||||
|
||||
/**
|
||||
* Process a set operation for FileBasicInformation. From the documentation,
|
||||
* this is "used to set file information such as the times of creation, last
|
||||
* access, last write, and change, in addition to file attributes."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int length);
|
||||
guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_basic_info;
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "channels/rdpdr/rdpdr-messages.h"
|
||||
#include "channels/rdpdr/rdpdr-fs-messages-vol-info.h"
|
||||
#include "channels/rdpdr/rdpdr-fs.h"
|
||||
#include "channels/rdpdr/rdpdr.h"
|
||||
#include "fs.h"
|
||||
|
||||
@ -28,15 +30,14 @@
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 21 + GUAC_FILESYSTEM_LABEL_LENGTH);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 21 + GUAC_FILESYSTEM_LABEL_LENGTH);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 17 + GUAC_FILESYSTEM_LABEL_LENGTH);
|
||||
Stream_Write_UINT64(output_stream, 0); /* VolumeCreationTime */
|
||||
@ -51,18 +52,17 @@ void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
guac_rdp_fs_info info = {0};
|
||||
guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info);
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 28);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 28);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 24);
|
||||
Stream_Write_UINT64(output_stream, info.blocks_total); /* TotalAllocationUnits */
|
||||
@ -75,15 +75,14 @@ void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 12);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 12);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 8);
|
||||
Stream_Write_UINT32(output_stream, FILE_DEVICE_DISK); /* DeviceType */
|
||||
@ -94,17 +93,16 @@ void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
int name_len = guac_utf8_strlen(device->device_name);
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 16 + name_len);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 16 + name_len);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 12 + name_len);
|
||||
Stream_Write_UINT32(output_stream,
|
||||
@ -120,18 +118,17 @@ void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
guac_rdp_fs_info info = {0};
|
||||
guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info);
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 36);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 36);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
|
||||
iorequest->file_id);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 32);
|
||||
Stream_Write_UINT64(output_stream, info.blocks_total); /* TotalAllocationUnits */
|
||||
|
@ -38,37 +38,27 @@
|
||||
* documentation, this is "used to query information for a volume on which a
|
||||
* file system is mounted."
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_volume_info;
|
||||
|
||||
/**
|
||||
* Processes a query request for FileFsSizeInformation.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_size_info;
|
||||
|
||||
/**
|
||||
* Processes a query request for FileFsAttributeInformation.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_attribute_info;
|
||||
|
||||
/**
|
||||
* Processes a query request for FileFsFullSizeInformation.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_full_size_info;
|
||||
|
||||
/**
|
||||
* Processes a query request for FileFsDeviceInformation.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_device_info;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -39,7 +39,8 @@
|
||||
#include <string.h>
|
||||
|
||||
void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream;
|
||||
int file_id;
|
||||
@ -79,8 +80,8 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
||||
guac_client_log(svc->client, GUAC_LOG_ERROR,
|
||||
"File open refused (%i): \"%s\"", file_id, path);
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
guac_rdp_fs_get_status(file_id), 5);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, guac_rdp_fs_get_status(file_id), 5);
|
||||
Stream_Write_UINT32(output_stream, 0); /* fileId */
|
||||
Stream_Write_UINT8(output_stream, 0); /* information */
|
||||
}
|
||||
@ -90,8 +91,8 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
||||
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 5);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS, 5);
|
||||
Stream_Write_UINT32(output_stream, file_id); /* fileId */
|
||||
Stream_Write_UINT8(output_stream, 0); /* information */
|
||||
|
||||
@ -113,8 +114,8 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
UINT32 length;
|
||||
UINT64 offset;
|
||||
@ -129,7 +130,7 @@ void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] length=%i, offset=%" PRIu64,
|
||||
__func__, file_id, length, (uint64_t) offset);
|
||||
__func__, iorequest->file_id, length, (uint64_t) offset);
|
||||
|
||||
/* Ensure buffer size does not exceed a safe maximum */
|
||||
if (length > GUAC_RDP_MAX_READ_BUFFER)
|
||||
@ -139,20 +140,20 @@ void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
|
||||
buffer = malloc(length);
|
||||
|
||||
/* Attempt read */
|
||||
bytes_read = guac_rdp_fs_read((guac_rdp_fs*) device->data, file_id, offset,
|
||||
buffer, length);
|
||||
bytes_read = guac_rdp_fs_read((guac_rdp_fs*) device->data,
|
||||
iorequest->file_id, offset, buffer, length);
|
||||
|
||||
/* If error, return invalid parameter */
|
||||
if (bytes_read < 0) {
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
guac_rdp_fs_get_status(bytes_read), 4);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, guac_rdp_fs_get_status(bytes_read), 4);
|
||||
Stream_Write_UINT32(output_stream, 0); /* Length */
|
||||
}
|
||||
|
||||
/* Otherwise, send bytes read */
|
||||
else {
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 4+bytes_read);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4+bytes_read);
|
||||
Stream_Write_UINT32(output_stream, bytes_read); /* Length */
|
||||
Stream_Write(output_stream, buffer, bytes_read); /* ReadData */
|
||||
}
|
||||
@ -163,8 +164,8 @@ void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
UINT32 length;
|
||||
UINT64 offset;
|
||||
@ -179,24 +180,24 @@ void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] length=%i, offset=%" PRIu64,
|
||||
__func__, file_id, length, (uint64_t) offset);
|
||||
__func__, iorequest->file_id, length, (uint64_t) offset);
|
||||
|
||||
/* Attempt write */
|
||||
bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data, file_id,
|
||||
offset, Stream_Pointer(input_stream), length);
|
||||
bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data,
|
||||
iorequest->file_id, offset, Stream_Pointer(input_stream), length);
|
||||
|
||||
/* If error, return invalid parameter */
|
||||
if (bytes_written < 0) {
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
guac_rdp_fs_get_status(bytes_written), 5);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, guac_rdp_fs_get_status(bytes_written), 5);
|
||||
Stream_Write_UINT32(output_stream, 0); /* Length */
|
||||
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
||||
}
|
||||
|
||||
/* Otherwise, send success */
|
||||
else {
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 5);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS, 5);
|
||||
Stream_Write_UINT32(output_stream, bytes_written); /* Length */
|
||||
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
||||
}
|
||||
@ -206,18 +207,17 @@ void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream;
|
||||
guac_rdp_fs_file* file;
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i]",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]",
|
||||
__func__, iorequest->file_id);
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
@ -225,14 +225,14 @@ void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc,
|
||||
if (file->bytes_written > 0 &&
|
||||
strncmp(file->absolute_path, "\\Download\\", 10) == 0) {
|
||||
guac_rdpdr_start_download(svc, device, file->absolute_path);
|
||||
guac_rdp_fs_delete((guac_rdp_fs*) device->data, file_id);
|
||||
guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
}
|
||||
|
||||
/* Close file */
|
||||
guac_rdp_fs_close((guac_rdp_fs*) device->data, file_id);
|
||||
guac_rdp_fs_close((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_SUCCESS, 4);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */
|
||||
|
||||
guac_rdp_common_svc_write(svc, output_stream);
|
||||
@ -240,8 +240,8 @@ void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
int fs_information_class;
|
||||
|
||||
@ -251,28 +251,23 @@ void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc,
|
||||
switch (fs_information_class) {
|
||||
|
||||
case FileFsVolumeInformation:
|
||||
guac_rdpdr_fs_process_query_volume_info(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_query_volume_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
case FileFsSizeInformation:
|
||||
guac_rdpdr_fs_process_query_size_info(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_query_size_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
case FileFsDeviceInformation:
|
||||
guac_rdpdr_fs_process_query_device_info(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_query_device_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
case FileFsAttributeInformation:
|
||||
guac_rdpdr_fs_process_query_attribute_info(svc, device,
|
||||
input_stream, file_id, completion_id);
|
||||
guac_rdpdr_fs_process_query_attribute_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
case FileFsFullSizeInformation:
|
||||
guac_rdpdr_fs_process_query_full_size_info(svc, device,
|
||||
input_stream, file_id, completion_id);
|
||||
guac_rdpdr_fs_process_query_full_size_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -283,8 +278,8 @@ void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
int fs_information_class;
|
||||
|
||||
@ -294,18 +289,15 @@ void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc,
|
||||
switch (fs_information_class) {
|
||||
|
||||
case FileBasicInformation:
|
||||
guac_rdpdr_fs_process_query_basic_info(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_query_basic_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
case FileStandardInformation:
|
||||
guac_rdpdr_fs_process_query_standard_info(svc, device,
|
||||
input_stream, file_id, completion_id);
|
||||
guac_rdpdr_fs_process_query_standard_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
case FileAttributeTagInformation:
|
||||
guac_rdpdr_fs_process_query_attribute_tag_info(svc, device,
|
||||
input_stream, file_id, completion_id);
|
||||
guac_rdpdr_fs_process_query_attribute_tag_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -316,23 +308,23 @@ void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_NOT_SUPPORTED, 0);
|
||||
iorequest->completion_id, STATUS_NOT_SUPPORTED, 0);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] Set volume info not supported",
|
||||
__func__, file_id);
|
||||
__func__, iorequest->file_id);
|
||||
|
||||
guac_rdp_common_svc_write(svc, output_stream);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
int fs_information_class;
|
||||
int length;
|
||||
@ -345,28 +337,23 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc,
|
||||
switch (fs_information_class) {
|
||||
|
||||
case FileBasicInformation:
|
||||
guac_rdpdr_fs_process_set_basic_info(svc, device, input_stream,
|
||||
file_id, completion_id, length);
|
||||
guac_rdpdr_fs_process_set_basic_info(svc, device, iorequest, length, input_stream);
|
||||
break;
|
||||
|
||||
case FileEndOfFileInformation:
|
||||
guac_rdpdr_fs_process_set_end_of_file_info(svc, device,
|
||||
input_stream, file_id, completion_id, length);
|
||||
guac_rdpdr_fs_process_set_end_of_file_info(svc, device, iorequest, length, input_stream);
|
||||
break;
|
||||
|
||||
case FileDispositionInformation:
|
||||
guac_rdpdr_fs_process_set_disposition_info(svc, device,
|
||||
input_stream, file_id, completion_id, length);
|
||||
guac_rdpdr_fs_process_set_disposition_info(svc, device, iorequest, length, input_stream);
|
||||
break;
|
||||
|
||||
case FileRenameInformation:
|
||||
guac_rdpdr_fs_process_set_rename_info(svc, device, input_stream,
|
||||
file_id, completion_id, length);
|
||||
guac_rdpdr_fs_process_set_rename_info(svc, device, iorequest, length, input_stream);
|
||||
break;
|
||||
|
||||
case FileAllocationInformation:
|
||||
guac_rdpdr_fs_process_set_allocation_info(svc, device,
|
||||
input_stream, file_id, completion_id, length);
|
||||
guac_rdpdr_fs_process_set_allocation_info(svc, device, iorequest, length, input_stream);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -378,15 +365,14 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_INVALID_PARAMETER, 4);
|
||||
iorequest->completion_id, STATUS_INVALID_PARAMETER, 4);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] IGNORED",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED",
|
||||
__func__, iorequest->file_id);
|
||||
|
||||
/* No content for now */
|
||||
Stream_Write_UINT32(output_stream, 0);
|
||||
@ -396,18 +382,17 @@ void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] Not implemented",
|
||||
__func__, file_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Not "
|
||||
"implemented", __func__, iorequest->file_id);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream;
|
||||
|
||||
@ -418,7 +403,7 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||
const char* entry_name;
|
||||
|
||||
/* Get file */
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
|
||||
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
@ -438,13 +423,13 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||
|
||||
}
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] initial_query=%i, dir_pattern=\"%s\"",
|
||||
__func__, file_id, initial_query, file->dir_pattern);
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] "
|
||||
"initial_query=%i, dir_pattern=\"%s\"", __func__,
|
||||
iorequest->file_id, initial_query, file->dir_pattern);
|
||||
|
||||
/* Find first matching entry in directory */
|
||||
while ((entry_name = guac_rdp_fs_read_dir((guac_rdp_fs*) device->data,
|
||||
file_id)) != NULL) {
|
||||
iorequest->file_id)) != NULL) {
|
||||
|
||||
/* Convert to absolute path */
|
||||
char entry_path[GUAC_RDP_FS_MAX_PATH];
|
||||
@ -468,24 +453,22 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||
|
||||
case FileDirectoryInformation:
|
||||
guac_rdpdr_fs_process_query_directory_info(svc, device,
|
||||
entry_name, entry_file_id, completion_id);
|
||||
iorequest, entry_name, entry_file_id);
|
||||
break;
|
||||
|
||||
case FileFullDirectoryInformation:
|
||||
guac_rdpdr_fs_process_query_full_directory_info(svc,
|
||||
device, entry_name, entry_file_id,
|
||||
completion_id);
|
||||
device, iorequest, entry_name, entry_file_id);
|
||||
break;
|
||||
|
||||
case FileBothDirectoryInformation:
|
||||
guac_rdpdr_fs_process_query_both_directory_info(svc,
|
||||
device, entry_name, entry_file_id,
|
||||
completion_id);
|
||||
device, iorequest, entry_name, entry_file_id);
|
||||
break;
|
||||
|
||||
case FileNamesInformation:
|
||||
guac_rdpdr_fs_process_query_names_info(svc, device,
|
||||
entry_name, entry_file_id, completion_id);
|
||||
iorequest, entry_name, entry_file_id);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -505,8 +488,8 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||
* Handle errors as a lack of files.
|
||||
*/
|
||||
|
||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||
STATUS_NO_MORE_FILES, 5);
|
||||
output_stream = guac_rdpdr_new_io_completion(device,
|
||||
iorequest->completion_id, STATUS_NO_MORE_FILES, 5);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 0); /* Length */
|
||||
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
||||
@ -516,15 +499,15 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_NOT_SUPPORTED, 5);
|
||||
iorequest->completion_id, STATUS_NOT_SUPPORTED, 5);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||
"%s: [file_id=%i] Lock not supported",
|
||||
__func__, file_id);
|
||||
__func__, iorequest->file_id);
|
||||
|
||||
Stream_Zero(output_stream, 5); /* Padding */
|
||||
|
||||
|
@ -37,37 +37,28 @@
|
||||
* Handles a Server Create Drive Request. Despite its name, this request opens
|
||||
* a file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_create;
|
||||
|
||||
/**
|
||||
* Handles a Server Close Drive Reqiest. This request closes an open file.
|
||||
* Handles a Server Close Drive Request. This request closes an open file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_close;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Read Request. This request reads from a file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_read;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Write Request. This request writes to a file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_write;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Control Request. This request handles one of any
|
||||
* number of Windows FSCTL_* control functions.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_device_control;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Query Volume Information Request. This request
|
||||
@ -75,60 +66,46 @@ void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc,
|
||||
* has several query types which have their own handlers defined in a
|
||||
* separate file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_volume_info;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Set Volume Information Request. Currently, this
|
||||
* RDPDR implementation does not support setting of volume information.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_set_volume_info;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Query Information Request. This request queries
|
||||
* information about a specific file. This request has several query types
|
||||
* which have their own handlers defined in a separate file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_file_info;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Set Information Request. This request sets
|
||||
* information about a specific file. Currently, this RDPDR implementation does
|
||||
* not support setting of file information.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_set_file_info;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Query Directory Request. This request queries
|
||||
* information about a specific directory. This request has several query types
|
||||
* which have their own handlers defined in a separate file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_directory;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive NotifyChange Directory Request. This request requests
|
||||
* directory change notification.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_notify_change_directory;
|
||||
|
||||
/**
|
||||
* Handles a Server Drive Lock Control Request. This request locks or unlocks
|
||||
* portions of a file.
|
||||
*/
|
||||
void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id);
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_lock_control;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "channels/rdpdr/rdpdr-fs-messages.h"
|
||||
#include "channels/rdpdr/rdpdr-fs.h"
|
||||
#include "channels/rdpdr/rdpdr-messages.h"
|
||||
#include "channels/rdpdr/rdpdr.h"
|
||||
#include "rdp.h"
|
||||
@ -30,96 +31,85 @@
|
||||
#include <guacamole/unicode.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
static void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int major_func, int minor_func) {
|
||||
void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
switch (major_func) {
|
||||
switch (iorequest->major_func) {
|
||||
|
||||
/* File open */
|
||||
case IRP_MJ_CREATE:
|
||||
guac_rdpdr_fs_process_create(svc, device, input_stream,
|
||||
completion_id);
|
||||
guac_rdpdr_fs_process_create(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* File close */
|
||||
case IRP_MJ_CLOSE:
|
||||
guac_rdpdr_fs_process_close(svc, device, input_stream, file_id,
|
||||
completion_id);
|
||||
guac_rdpdr_fs_process_close(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* File read */
|
||||
case IRP_MJ_READ:
|
||||
guac_rdpdr_fs_process_read(svc, device, input_stream, file_id,
|
||||
completion_id);
|
||||
guac_rdpdr_fs_process_read(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* File write */
|
||||
case IRP_MJ_WRITE:
|
||||
guac_rdpdr_fs_process_write(svc, device, input_stream, file_id,
|
||||
completion_id);
|
||||
guac_rdpdr_fs_process_write(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* Device control request (Windows FSCTL_ control codes) */
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
guac_rdpdr_fs_process_device_control(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_device_control(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* Query volume (drive) information */
|
||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
||||
guac_rdpdr_fs_process_volume_info(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_volume_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* Set volume (drive) information */
|
||||
case IRP_MJ_SET_VOLUME_INFORMATION:
|
||||
guac_rdpdr_fs_process_set_volume_info(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_set_volume_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* Query file information */
|
||||
case IRP_MJ_QUERY_INFORMATION:
|
||||
guac_rdpdr_fs_process_file_info(svc, device, input_stream, file_id,
|
||||
completion_id);
|
||||
guac_rdpdr_fs_process_file_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* Set file information */
|
||||
case IRP_MJ_SET_INFORMATION:
|
||||
guac_rdpdr_fs_process_set_file_info(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_set_file_info(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
case IRP_MJ_DIRECTORY_CONTROL:
|
||||
|
||||
/* Enumerate directory contents */
|
||||
if (minor_func == IRP_MN_QUERY_DIRECTORY)
|
||||
guac_rdpdr_fs_process_query_directory(svc, device,
|
||||
input_stream, file_id, completion_id);
|
||||
if (iorequest->minor_func == IRP_MN_QUERY_DIRECTORY)
|
||||
guac_rdpdr_fs_process_query_directory(svc, device, iorequest,
|
||||
input_stream);
|
||||
|
||||
/* Request notification of changes to directory */
|
||||
else if (minor_func == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
|
||||
else if (iorequest->minor_func == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
|
||||
guac_rdpdr_fs_process_notify_change_directory(svc, device,
|
||||
input_stream,
|
||||
file_id, completion_id);
|
||||
iorequest, input_stream);
|
||||
|
||||
break;
|
||||
|
||||
/* Lock/unlock portions of a file */
|
||||
case IRP_MJ_LOCK_CONTROL:
|
||||
guac_rdpdr_fs_process_lock_control(svc, device, input_stream,
|
||||
file_id, completion_id);
|
||||
guac_rdpdr_fs_process_lock_control(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
default:
|
||||
guac_client_log(svc->client, GUAC_LOG_ERROR,
|
||||
"Unknown filesystem I/O request function: 0x%x/0x%x",
|
||||
major_func, minor_func);
|
||||
iorequest->major_func, iorequest->minor_func);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void guac_rdpdr_device_fs_free_handler(guac_rdp_common_svc* svc,
|
||||
void guac_rdpdr_device_fs_free_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device) {
|
||||
|
||||
Stream_Free(device->device_announce, 1);
|
||||
|
@ -36,6 +36,16 @@
|
||||
|
||||
#include <guacamole/pool.h>
|
||||
|
||||
/**
|
||||
* The UTF-16 string that should be sent as the label of the filesystem.
|
||||
*/
|
||||
#define GUAC_FILESYSTEM_LABEL "G\0U\0A\0C\0F\0I\0L\0E\0"
|
||||
|
||||
/**
|
||||
* The size of GUAC_FILESYSTEM_LABEL in bytes.
|
||||
*/
|
||||
#define GUAC_FILESYSTEM_LABEL_LENGTH 16
|
||||
|
||||
/**
|
||||
* Registers a new filesystem device within the RDPDR plugin. This must be done
|
||||
* before RDPDR connection finishes.
|
||||
|
@ -31,6 +31,28 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Sends a Client Announce Reply message. The Client Announce Reply message is
|
||||
* required to be sent in response to the Server Announce Request message. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/d6fe6d1b-c145-4a6f-99aa-4fe3cdcea398
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*
|
||||
* @param major
|
||||
* The major version of the RDPDR protocol in use. This value must always
|
||||
* be 1.
|
||||
*
|
||||
* @param minor
|
||||
* The minor version of the RDPDR protocol in use. This value must be
|
||||
* either 2, 5, 10, 12, or 13.
|
||||
*
|
||||
* @param client_id
|
||||
* The client ID received in the Server Announce Request, or a randomly
|
||||
* generated ID.
|
||||
*/
|
||||
static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc,
|
||||
unsigned int major, unsigned int minor, unsigned int client_id) {
|
||||
|
||||
@ -49,6 +71,19 @@ static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a Client Name Request message. The Client Name Request message is used
|
||||
* by the client to announce its own name. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/902497f1-3b1c-4aee-95f8-1668f9b7b7d2
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*
|
||||
* @param name
|
||||
* The name that should be used for the client.
|
||||
*/
|
||||
static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc,
|
||||
const char* name) {
|
||||
|
||||
@ -69,6 +104,18 @@ static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a Client Core Capability Response message. The Client Core Capability
|
||||
* Response message is used to announce the client's capabilities, in response
|
||||
* to receiving the server's capabilities via a Server Core Capability Request.
|
||||
* See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/f513bf87-cca0-488a-ac5c-18cf18f4a7e1
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*/
|
||||
static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) {
|
||||
|
||||
wStream* output_stream = Stream_New(NULL, 256);
|
||||
@ -117,6 +164,17 @@ static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a Client Device List Announce Request message. The Client Device List
|
||||
* Announce Request message is used by the client to enumerate all devices
|
||||
* which should be made available within the RDP session via RDPDR. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*/
|
||||
static void guac_rdpdr_send_client_device_list_announce_request(guac_rdp_common_svc* svc) {
|
||||
|
||||
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
||||
@ -220,28 +278,27 @@ void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc,
|
||||
wStream* input_stream) {
|
||||
|
||||
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
||||
|
||||
int device_id, file_id, completion_id, major_func, minor_func;
|
||||
guac_rdpdr_iorequest iorequest;
|
||||
|
||||
/* Read header */
|
||||
Stream_Read_UINT32(input_stream, device_id);
|
||||
Stream_Read_UINT32(input_stream, file_id);
|
||||
Stream_Read_UINT32(input_stream, completion_id);
|
||||
Stream_Read_UINT32(input_stream, major_func);
|
||||
Stream_Read_UINT32(input_stream, minor_func);
|
||||
Stream_Read_UINT32(input_stream, iorequest.device_id);
|
||||
Stream_Read_UINT32(input_stream, iorequest.file_id);
|
||||
Stream_Read_UINT32(input_stream, iorequest.completion_id);
|
||||
Stream_Read_UINT32(input_stream, iorequest.major_func);
|
||||
Stream_Read_UINT32(input_stream, iorequest.minor_func);
|
||||
|
||||
/* If printer, run printer handlers */
|
||||
if (device_id >= 0 && device_id < rdpdr->devices_registered) {
|
||||
if (iorequest.device_id >= 0 && iorequest.device_id < rdpdr->devices_registered) {
|
||||
|
||||
/* Call handler on device */
|
||||
guac_rdpdr_device* device = &(rdpdr->devices[device_id]);
|
||||
device->iorequest_handler(svc, device, input_stream,
|
||||
file_id, completion_id, major_func, minor_func);
|
||||
guac_rdpdr_device* device = &(rdpdr->devices[iorequest.device_id]);
|
||||
device->iorequest_handler(svc, device, &iorequest, input_stream);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id);
|
||||
guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: "
|
||||
"0x%08x", iorequest.device_id);
|
||||
|
||||
}
|
||||
|
||||
|
@ -35,29 +35,102 @@
|
||||
#define GUAC_OS_TYPE (*((uint32_t*) "GUAC"))
|
||||
|
||||
/**
|
||||
* Name of the printer driver that should be used on the server.
|
||||
* Handler which processes a message specific to the RDPDR channel.
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*
|
||||
* @param input_stream
|
||||
* A wStream containing the entire received message.
|
||||
*/
|
||||
#define GUAC_PRINTER_DRIVER "M\0S\0 \0P\0u\0b\0l\0i\0s\0h\0e\0r\0 \0I\0m\0a\0g\0e\0s\0e\0t\0t\0e\0r\0\0\0"
|
||||
#define GUAC_PRINTER_DRIVER_LENGTH 50
|
||||
typedef void guac_rdpdr_message_handler(guac_rdp_common_svc* svc,
|
||||
wStream* input_stream);
|
||||
|
||||
/**
|
||||
* Label of the filesystem.
|
||||
* Handler which processes a received Server Announce Request message. The
|
||||
* Server Announce Request message begins the RDPDR exchange and provides a
|
||||
* client ID which the RDPDR client may use. The client may also supply its
|
||||
* own, randomly-generated ID, and is required to do so for older versions of
|
||||
* RDPDR. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/046047aa-62d8-49f9-bf16-7fe41880aaf4
|
||||
*/
|
||||
#define GUAC_FILESYSTEM_LABEL "G\0U\0A\0C\0F\0I\0L\0E\0"
|
||||
#define GUAC_FILESYSTEM_LABEL_LENGTH 16
|
||||
guac_rdpdr_message_handler guac_rdpdr_process_server_announce;
|
||||
|
||||
/*
|
||||
* Message handlers.
|
||||
/**
|
||||
* Handler which processes a received Server Client ID Confirm message. The
|
||||
* Server Client ID Confirm message is sent by the server to confirm the client
|
||||
* ID requested by the client (in its response to the Server Announce Request)
|
||||
* has been accepted. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/bbbb9666-6994-4cf6-8e65-0d46eb319c6e
|
||||
*/
|
||||
guac_rdpdr_message_handler guac_rdpdr_process_clientid_confirm;
|
||||
|
||||
void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||
void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||
void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||
void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||
void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||
void guac_rdpdr_process_user_loggedon(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||
void guac_rdpdr_process_prn_cache_data(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||
void guac_rdpdr_process_prn_using_xps(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||
/**
|
||||
* Handler which processes a received Server Device Announce Response message.
|
||||
* The Server Device Announce Response message is sent in response to a Client
|
||||
* Device List Announce message to communicate the success/failure status of
|
||||
* device creation. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a4c0b619-6e87-4721-bdc4-5d2db7f485f3
|
||||
*/
|
||||
guac_rdpdr_message_handler guac_rdpdr_process_device_reply;
|
||||
|
||||
/**
|
||||
* Handler which processes a received Device I/O Request message. The Device
|
||||
* I/O Request message makes up the majority of traffic once RDPDR is
|
||||
* established. Each I/O request consists of a device-specific major/minor
|
||||
* function number pair, as well as several parameters. Device-specific
|
||||
* handling of I/O requests within Guacamole is delegated to device- and
|
||||
* function-specific implementations of yet another function type:
|
||||
* guac_rdpdr_device_iorequest_handler.
|
||||
*
|
||||
* See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d
|
||||
*/
|
||||
guac_rdpdr_message_handler guac_rdpdr_process_device_iorequest;
|
||||
|
||||
/**
|
||||
* Handler which processes a received Server Core Capability Request message.
|
||||
* The Server Core Capability Request message is sent by the server to
|
||||
* communicate its capabilities and to request that the client communicate the
|
||||
* same. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/702789c3-b924-4bc2-9280-3221bc7d6797
|
||||
*/
|
||||
guac_rdpdr_message_handler guac_rdpdr_process_server_capability;
|
||||
|
||||
/**
|
||||
* Handler which processes a received Server User Logged On message. The Server
|
||||
* User Logged On message is sent by the server to notify that the user has
|
||||
* logged on to the session. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/dfc0e8ed-a242-4d00-bb88-e779e08f2f61
|
||||
*/
|
||||
guac_rdpdr_message_handler guac_rdpdr_process_user_loggedon;
|
||||
|
||||
/**
|
||||
* Handler which processes any one of several RDPDR messages specific to cached
|
||||
* printer configuration data, each of these messages having the same
|
||||
* PAKID_PRN_CACHE_DATA packet ID. The Guacamole RDPDR implementation ignores
|
||||
* all PAKID_PRN_CACHE_DATA messages. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpepc/7fccae60-f077-433b-9dee-9bad4238bf40
|
||||
*/
|
||||
guac_rdpdr_message_handler guac_rdpdr_process_prn_cache_data;
|
||||
|
||||
/**
|
||||
* Handler which processes a received Server Printer Set XPS Mode message. The
|
||||
* Server Printer Set XPS Mode message is specific to printers and requests
|
||||
* that the client printer be set to XPS mode. The Guacamole RDPDR
|
||||
* implementation ignores any request to set the printer to XPS mode. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpepc/f1789a66-bcd0-4df3-bfc2-6e7330d63145
|
||||
*/
|
||||
guac_rdpdr_message_handler guac_rdpdr_process_prn_using_xps;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -43,7 +43,8 @@
|
||||
#include <unistd.h>
|
||||
|
||||
void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
guac_client* client = svc->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
@ -57,7 +58,7 @@ void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc,
|
||||
|
||||
/* Respond with success */
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 4);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 0); /* fileId */
|
||||
guac_rdp_common_svc_write(svc, output_stream);
|
||||
@ -65,7 +66,8 @@ void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
guac_client* client = svc->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
@ -94,7 +96,7 @@ void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, status, 5);
|
||||
iorequest->completion_id, status, 5);
|
||||
|
||||
Stream_Write_UINT32(output_stream, length);
|
||||
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
||||
@ -104,7 +106,8 @@ void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int completion_id) {
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
guac_client* client = svc->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
@ -117,7 +120,7 @@ void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc,
|
||||
}
|
||||
|
||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||
completion_id, STATUS_SUCCESS, 4);
|
||||
iorequest->completion_id, STATUS_SUCCESS, 4);
|
||||
|
||||
Stream_Write_UINT32(output_stream, 0); /* Padding */
|
||||
guac_rdp_common_svc_write(svc, output_stream);
|
||||
@ -127,41 +130,38 @@ void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc,
|
||||
|
||||
}
|
||||
|
||||
static void guac_rdpdr_device_printer_iorequest_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int major_func, int minor_func) {
|
||||
void guac_rdpdr_device_printer_iorequest_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream) {
|
||||
|
||||
switch (major_func) {
|
||||
switch (iorequest->major_func) {
|
||||
|
||||
/* Print job create */
|
||||
case IRP_MJ_CREATE:
|
||||
guac_rdpdr_process_print_job_create(svc, device, input_stream,
|
||||
completion_id);
|
||||
guac_rdpdr_process_print_job_create(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* Printer job write */
|
||||
case IRP_MJ_WRITE:
|
||||
guac_rdpdr_process_print_job_write(svc, device, input_stream,
|
||||
completion_id);
|
||||
guac_rdpdr_process_print_job_write(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* Printer job close */
|
||||
case IRP_MJ_CLOSE:
|
||||
guac_rdpdr_process_print_job_close(svc, device, input_stream,
|
||||
completion_id);
|
||||
guac_rdpdr_process_print_job_close(svc, device, iorequest, input_stream);
|
||||
break;
|
||||
|
||||
/* Log unknown */
|
||||
default:
|
||||
guac_client_log(svc->client, GUAC_LOG_ERROR,
|
||||
"Unknown printer I/O request function: 0x%x/0x%x",
|
||||
major_func, minor_func);
|
||||
guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown printer "
|
||||
"I/O request function: 0x%x/0x%x", iorequest->major_func,
|
||||
iorequest->minor_func);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void guac_rdpdr_device_printer_free_handler(guac_rdp_common_svc* svc,
|
||||
void guac_rdpdr_device_printer_free_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device) {
|
||||
|
||||
Stream_Free(device->device_announce, 1);
|
||||
|
@ -25,6 +25,16 @@
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/**
|
||||
* Name of the printer driver that should be used on the server.
|
||||
*/
|
||||
#define GUAC_PRINTER_DRIVER "M\0S\0 \0P\0u\0b\0l\0i\0s\0h\0e\0r\0 \0I\0m\0a\0g\0e\0s\0e\0t\0t\0e\0r\0\0\0"
|
||||
|
||||
/**
|
||||
* The size of GUAC_PRINTER_DRIVER in bytes.
|
||||
*/
|
||||
#define GUAC_PRINTER_DRIVER_LENGTH 50
|
||||
|
||||
/**
|
||||
* Registers a new printer device within the RDPDR plugin. This must be done
|
||||
* before RDPDR connection finishes.
|
||||
@ -38,5 +48,34 @@
|
||||
*/
|
||||
void guac_rdpdr_register_printer(guac_rdp_common_svc* svc, char* printer_name);
|
||||
|
||||
/**
|
||||
* I/O request handler which processes a print job creation request.
|
||||
*/
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_create;
|
||||
|
||||
/**
|
||||
* I/O request handler which processes a request to write data to an existing
|
||||
* print job.
|
||||
*/
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_write;
|
||||
|
||||
/**
|
||||
* I/O request handler which processes a request to close an existing print
|
||||
* job.
|
||||
*/
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_close;
|
||||
|
||||
/**
|
||||
* Handler for RDPDR Device I/O Requests which processes received messages on
|
||||
* behalf of a printer device, in this case a simulated printer which produces
|
||||
* PDF output.
|
||||
*/
|
||||
guac_rdpdr_device_iorequest_handler guac_rdpdr_device_printer_iorequest_handler;
|
||||
|
||||
/**
|
||||
* Free handler which frees all data specific to the simulated printer device.
|
||||
*/
|
||||
guac_rdpdr_device_free_handler guac_rdpdr_device_printer_free_handler;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -37,21 +37,79 @@
|
||||
typedef struct guac_rdpdr_device guac_rdpdr_device;
|
||||
|
||||
/**
|
||||
* Handler for client device list announce. Each implementing device must write
|
||||
* its announcement header and data to the given output stream.
|
||||
* The contents of the header common to all RDPDR Device I/O Requests. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d
|
||||
*/
|
||||
typedef void guac_rdpdr_device_announce_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* output_stream, int device_id);
|
||||
typedef struct guac_rdpdr_iorequest {
|
||||
|
||||
/**
|
||||
* Handler for device I/O requests.
|
||||
* The unique ID assigned to the device receiving this I/O request.
|
||||
*/
|
||||
int device_id;
|
||||
|
||||
/**
|
||||
* The unique ID which identifies the relevant file, as returned when the
|
||||
* file was opened. This field may not be relevant to all requests.
|
||||
*/
|
||||
int file_id;
|
||||
|
||||
/**
|
||||
* The unique ID that should be used to refer to this I/O request in future
|
||||
* responses.
|
||||
*/
|
||||
int completion_id;
|
||||
|
||||
/**
|
||||
* Integer ID which identifies the function being requested, such as
|
||||
* IRP_MJ_CREATE (open a file within a shared drive) or IRP_MJ_WRITE (write
|
||||
* data to an open file).
|
||||
*/
|
||||
int major_func;
|
||||
|
||||
/**
|
||||
* Integer ID which identifies a variant of the function denoted by
|
||||
* major_func. This value is only valid for IRP_MJ_DIRECTORY_CONTROL.
|
||||
*/
|
||||
int minor_func;
|
||||
|
||||
} guac_rdpdr_iorequest;
|
||||
|
||||
/**
|
||||
* Handler for Device I/O Requests. RDPDR devices must provide an
|
||||
* implementation of this function to be able to handle inbound I/O requests.
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*
|
||||
* @param device
|
||||
* The guac_rdpdr_device of the relevant device, as dictated by the
|
||||
* deviceId field of common RDPDR header within the received PDU. Within
|
||||
* the guac_rdpdr_iorequest structure, the deviceId field is stored within
|
||||
* device_id.
|
||||
*
|
||||
* @param iorequest
|
||||
* The contents of the common RDPDR Device I/O Request header shared by all
|
||||
* RDPDR devices.
|
||||
*
|
||||
* @param input_stream
|
||||
* The remaining data within the received PDU, following the common RDPDR
|
||||
* Device I/O Request header.
|
||||
*/
|
||||
typedef void guac_rdpdr_device_iorequest_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||
int completion_id, int major_func, int minor_func);
|
||||
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
|
||||
wStream* input_stream);
|
||||
|
||||
/**
|
||||
* Handler for cleaning up the dynamically-allocated portions of a device.
|
||||
*
|
||||
* @param svc
|
||||
* The guac_rdp_common_svc representing the static virtual channel being
|
||||
* used for RDPDR.
|
||||
*
|
||||
* @param device
|
||||
* The guac_rdpdr_device of the device being freed.
|
||||
*/
|
||||
typedef void guac_rdpdr_device_free_handler(guac_rdp_common_svc* svc,
|
||||
guac_rdpdr_device* device);
|
||||
@ -126,7 +184,30 @@ typedef struct guac_rdpdr {
|
||||
|
||||
/**
|
||||
* Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header
|
||||
* used for virtually all responses.
|
||||
* used for virtually all responses. Depending on the specific I/O completion
|
||||
* being sent, additional space may be reserved within the resulting stream for
|
||||
* additional fields. See:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a
|
||||
*
|
||||
* @param device
|
||||
* The device that completed the operation requested by a prior I/O
|
||||
* request.
|
||||
*
|
||||
* @param completion_id
|
||||
* The completion ID of the I/O request that requested the operation.
|
||||
*
|
||||
* @param status
|
||||
* An NTSTATUS code describing the success/failure of the operation that
|
||||
* was completed.
|
||||
*
|
||||
* @param size
|
||||
* The number of additional bytes to reserve at the end of the resulting
|
||||
* stream for additional fields to be appended.
|
||||
*
|
||||
* @return
|
||||
* A new wStream containing an I/O completion header, followed by the
|
||||
* requested additional free space.
|
||||
*/
|
||||
wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
|
||||
int completion_id, int status, int size);
|
||||
|
Loading…
Reference in New Issue
Block a user