in src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c [463:587]
void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
wStream* input_stream) {
wStream* output_stream;
guac_rdp_fs_file* file;
int fs_information_class, initial_query;
int path_length;
const char* entry_name;
/* Get file */
file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
if (file == NULL)
return;
if (Stream_GetRemainingLength(input_stream) < 9) {
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
"Directory PDU does not contain the expected number of bytes. "
"Drive redirection may not work as expected.");
return;
}
/* Read main header */
Stream_Read_UINT32(input_stream, fs_information_class);
Stream_Read_UINT8(input_stream, initial_query);
Stream_Read_UINT32(input_stream, path_length);
/* If this is the first query, the path is included after padding */
if (initial_query) {
/*
* Check to make sure Stream has at least the 23 padding bytes in it
* prior to seeking.
*/
if (Stream_GetRemainingLength(input_stream) < (23 + path_length)) {
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
"Directory PDU does not contain the expected number of "
"bytes. Drive redirection may not work as expected.");
return;
}
Stream_Seek(input_stream, 23); /* Padding */
/* Convert path to UTF-8 */
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1,
file->dir_pattern, sizeof(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,
iorequest->file_id)) != NULL) {
/* Convert to absolute path */
char entry_path[GUAC_RDP_FS_MAX_PATH];
if (guac_rdp_fs_convert_path(file->absolute_path,
entry_name, entry_path) == 0) {
int entry_file_id;
/* Pattern defined and match fails, continue with next file */
if (guac_rdp_fs_matches(entry_path, file->dir_pattern))
continue;
/* Open directory entry */
entry_file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data,
entry_path, FILE_READ_DATA, 0, FILE_OPEN, 0);
if (entry_file_id >= 0) {
/* Dispatch to appropriate class-specific handler */
switch (fs_information_class) {
case FileDirectoryInformation:
guac_rdpdr_fs_process_query_directory_info(svc, device,
iorequest, entry_name, entry_file_id);
break;
case FileFullDirectoryInformation:
guac_rdpdr_fs_process_query_full_directory_info(svc,
device, iorequest, entry_name, entry_file_id);
break;
case FileBothDirectoryInformation:
guac_rdpdr_fs_process_query_both_directory_info(svc,
device, iorequest, entry_name, entry_file_id);
break;
case FileNamesInformation:
guac_rdpdr_fs_process_query_names_info(svc, device,
iorequest, entry_name, entry_file_id);
break;
default:
guac_client_log(svc->client, GUAC_LOG_DEBUG,
"Unknown dir information class: 0x%x",
fs_information_class);
}
guac_rdp_fs_close((guac_rdp_fs*) device->data, entry_file_id);
return;
} /* end if file exists */
} /* end if path valid */
} /* end if entry exists */
/*
* Handle errors as a lack of files.
*/
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 */
guac_rdp_common_svc_write(svc, output_stream);
}