GUACAMOLE-249: VirtualChannelEntryEx entry point is supposed to accept a PCHANNEL_ENTRY_POINTS_EX.
This commit is contained in:
parent
4612e79b8d
commit
664586ea54
@ -62,6 +62,13 @@ libguac_client_rdp_la_SOURCES = \
|
|||||||
rdp_settings.c \
|
rdp_settings.c \
|
||||||
rdp_stream.c \
|
rdp_stream.c \
|
||||||
rdpdr.c \
|
rdpdr.c \
|
||||||
|
rdpdr_fs_messages.c \
|
||||||
|
rdpdr_fs_messages_dir_info.c \
|
||||||
|
rdpdr_fs_messages_file_info.c \
|
||||||
|
rdpdr_fs_messages_vol_info.c \
|
||||||
|
rdpdr_fs_service.c \
|
||||||
|
rdpdr_messages.c \
|
||||||
|
rdpdr_printer.c \
|
||||||
rdpsnd.c \
|
rdpsnd.c \
|
||||||
rdpsnd_messages.c \
|
rdpsnd_messages.c \
|
||||||
resolution.c \
|
resolution.c \
|
||||||
@ -71,14 +78,6 @@ libguac_client_rdp_la_SOURCES = \
|
|||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
guac_ai/ai_messages.h \
|
guac_ai/ai_messages.h \
|
||||||
guac_ai/ai_service.h \
|
guac_ai/ai_service.h \
|
||||||
guac_rdpdr/rdpdr_fs_messages.h \
|
|
||||||
guac_rdpdr/rdpdr_fs_messages_dir_info.h \
|
|
||||||
guac_rdpdr/rdpdr_fs_messages_file_info.h \
|
|
||||||
guac_rdpdr/rdpdr_fs_messages_vol_info.h \
|
|
||||||
guac_rdpdr/rdpdr_fs_service.h \
|
|
||||||
guac_rdpdr/rdpdr_messages.h \
|
|
||||||
guac_rdpdr/rdpdr_printer.h \
|
|
||||||
guac_rdpdr/rdpdr_service.h \
|
|
||||||
audio_input.h \
|
audio_input.h \
|
||||||
client.h \
|
client.h \
|
||||||
clipboard.h \
|
clipboard.h \
|
||||||
@ -105,6 +104,13 @@ noinst_HEADERS = \
|
|||||||
rdp_status.h \
|
rdp_status.h \
|
||||||
rdp_stream.h \
|
rdp_stream.h \
|
||||||
rdpdr.h \
|
rdpdr.h \
|
||||||
|
rdpdr_fs_messages.h \
|
||||||
|
rdpdr_fs_messages_dir_info.h \
|
||||||
|
rdpdr_fs_messages_file_info.h \
|
||||||
|
rdpdr_fs_messages_vol_info.h \
|
||||||
|
rdpdr_fs_service.h \
|
||||||
|
rdpdr_messages.h \
|
||||||
|
rdpdr_printer.h \
|
||||||
rdpsnd.h \
|
rdpsnd.h \
|
||||||
rdpsnd_messages.h \
|
rdpsnd_messages.h \
|
||||||
resolution.h \
|
resolution.h \
|
||||||
@ -134,8 +140,7 @@ libguac_client_rdp_la_LIBADD = \
|
|||||||
|
|
||||||
freerdp_LTLIBRARIES = \
|
freerdp_LTLIBRARIES = \
|
||||||
libguac-common-svc-client.la \
|
libguac-common-svc-client.la \
|
||||||
libguacai-client.la \
|
libguacai-client.la
|
||||||
libguacdr-client.la
|
|
||||||
|
|
||||||
freerdpdir = ${libdir}/freerdp2
|
freerdpdir = ${libdir}/freerdp2
|
||||||
|
|
||||||
@ -158,40 +163,6 @@ libguac_common_svc_client_la_LDFLAGS = \
|
|||||||
libguac_common_svc_client_la_LIBADD = \
|
libguac_common_svc_client_la_LIBADD = \
|
||||||
@LIBGUAC_LTLIB@
|
@LIBGUAC_LTLIB@
|
||||||
|
|
||||||
#
|
|
||||||
# RDPDR
|
|
||||||
#
|
|
||||||
|
|
||||||
libguacdr_client_la_SOURCES = \
|
|
||||||
guac_rdpdr/rdpdr_fs_messages.c \
|
|
||||||
guac_rdpdr/rdpdr_fs_messages_dir_info.c \
|
|
||||||
guac_rdpdr/rdpdr_fs_messages_file_info.c \
|
|
||||||
guac_rdpdr/rdpdr_fs_messages_vol_info.c \
|
|
||||||
guac_rdpdr/rdpdr_fs_service.c \
|
|
||||||
guac_rdpdr/rdpdr_messages.c \
|
|
||||||
guac_rdpdr/rdpdr_printer.c \
|
|
||||||
guac_rdpdr/rdpdr_service.c \
|
|
||||||
rdp_fs.c \
|
|
||||||
rdp_print_job.c \
|
|
||||||
rdp_stream.c \
|
|
||||||
unicode.c
|
|
||||||
|
|
||||||
libguacdr_client_la_CFLAGS = \
|
|
||||||
-Werror -Wall -Iinclude \
|
|
||||||
@COMMON_INCLUDE@ \
|
|
||||||
@COMMON_SSH_INCLUDE@ \
|
|
||||||
@LIBGUAC_INCLUDE@ \
|
|
||||||
@RDP_CFLAGS@
|
|
||||||
|
|
||||||
libguacdr_client_la_LDFLAGS = \
|
|
||||||
-module -avoid-version -shared \
|
|
||||||
@PTHREAD_LIBS@ \
|
|
||||||
@RDP_LIBS@
|
|
||||||
|
|
||||||
libguacdr_client_la_LIBADD = \
|
|
||||||
@COMMON_LTLIB@ \
|
|
||||||
@LIBGUAC_LTLIB@
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Audio Input
|
# Audio Input
|
||||||
#
|
#
|
||||||
|
@ -283,7 +283,7 @@ static VOID guac_rdp_common_svc_handle_init_event(LPVOID user_param,
|
|||||||
* @return
|
* @return
|
||||||
* TRUE if the plugin has initialized successfully, FALSE otherwise.
|
* TRUE if the plugin has initialized successfully, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points,
|
BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX entry_points,
|
||||||
PVOID init_handle) {
|
PVOID init_handle) {
|
||||||
|
|
||||||
CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex =
|
CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex =
|
||||||
|
@ -1,500 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "rdp.h"
|
|
||||||
#include "rdp_fs.h"
|
|
||||||
#include "rdp_settings.h"
|
|
||||||
#include "rdp_stream.h"
|
|
||||||
#include "rdpdr_fs_service.h"
|
|
||||||
#include "rdpdr_messages.h"
|
|
||||||
#include "rdpdr_printer.h"
|
|
||||||
#include "rdpdr_service.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <freerdp/constants.h>
|
|
||||||
#include <guacamole/client.h>
|
|
||||||
#include <guacamole/protocol.h>
|
|
||||||
#include <guacamole/socket.h>
|
|
||||||
#include <guacamole/stream.h>
|
|
||||||
#include <winpr/stream.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes data received along the RDPDR channel via a
|
|
||||||
* CHANNEL_EVENT_DATA_RECEIVED event, forwarding the data along an established,
|
|
||||||
* outbound pipe stream to the Guacamole client.
|
|
||||||
*
|
|
||||||
* @param rdpdr
|
|
||||||
* The guac_rdpdr structure representing the RDPDR channel.
|
|
||||||
*
|
|
||||||
* @param input_stream
|
|
||||||
* The data that was received.
|
|
||||||
*/
|
|
||||||
static void guac_rdpdr_process_receive(guac_rdpdr* rdpdr,
|
|
||||||
wStream* input_stream) {
|
|
||||||
|
|
||||||
int component;
|
|
||||||
int packet_id;
|
|
||||||
|
|
||||||
/* Read header */
|
|
||||||
Stream_Read_UINT16(input_stream, component);
|
|
||||||
Stream_Read_UINT16(input_stream, packet_id);
|
|
||||||
|
|
||||||
/* Core component */
|
|
||||||
if (component == RDPDR_CTYP_CORE) {
|
|
||||||
|
|
||||||
/* Dispatch handlers based on packet ID */
|
|
||||||
switch (packet_id) {
|
|
||||||
|
|
||||||
case PAKID_CORE_SERVER_ANNOUNCE:
|
|
||||||
guac_rdpdr_process_server_announce(rdpdr, input_stream);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAKID_CORE_CLIENTID_CONFIRM:
|
|
||||||
guac_rdpdr_process_clientid_confirm(rdpdr, input_stream);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAKID_CORE_DEVICE_REPLY:
|
|
||||||
guac_rdpdr_process_device_reply(rdpdr, input_stream);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAKID_CORE_DEVICE_IOREQUEST:
|
|
||||||
guac_rdpdr_process_device_iorequest(rdpdr, input_stream);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAKID_CORE_SERVER_CAPABILITY:
|
|
||||||
guac_rdpdr_process_server_capability(rdpdr, input_stream);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAKID_CORE_USER_LOGGEDON:
|
|
||||||
guac_rdpdr_process_user_loggedon(rdpdr, input_stream);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring RDPDR core packet with unexpected ID: 0x%04x", packet_id);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* end if core */
|
|
||||||
|
|
||||||
/* Printer component */
|
|
||||||
else if (component == RDPDR_CTYP_PRN) {
|
|
||||||
|
|
||||||
/* Dispatch handlers based on packet ID */
|
|
||||||
switch (packet_id) {
|
|
||||||
|
|
||||||
case PAKID_PRN_CACHE_DATA:
|
|
||||||
guac_rdpdr_process_prn_cache_data(rdpdr, input_stream);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAKID_PRN_USING_XPS:
|
|
||||||
guac_rdpdr_process_prn_using_xps(rdpdr, input_stream);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring RDPDR printer packet with unexpected ID: 0x%04x", packet_id);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* end if printer */
|
|
||||||
|
|
||||||
else
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring packet for unknown RDPDR component: 0x%04x", component);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
|
|
||||||
int completion_id, int status, int size) {
|
|
||||||
|
|
||||||
wStream* output_stream = Stream_New(NULL, 16+size);
|
|
||||||
|
|
||||||
/* Write header */
|
|
||||||
Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
|
|
||||||
Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICE_IOCOMPLETION);
|
|
||||||
|
|
||||||
/* Write content */
|
|
||||||
Stream_Write_UINT32(output_stream, device->device_id);
|
|
||||||
Stream_Write_UINT32(output_stream, completion_id);
|
|
||||||
Stream_Write_UINT32(output_stream, status);
|
|
||||||
|
|
||||||
return output_stream;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback invoked on the current connection owner (if any) when a file
|
|
||||||
* download is being initiated using the magic "Download" folder.
|
|
||||||
*
|
|
||||||
* @param owner
|
|
||||||
* The guac_user that is the owner of the connection, or NULL if the
|
|
||||||
* connection owner has left.
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* The full absolute path to the file that should be downloaded.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The stream allocated for the file download, or NULL if the download has
|
|
||||||
* failed to start.
|
|
||||||
*/
|
|
||||||
static void* guac_rdpdr_download_to_owner(guac_user* owner, void* data) {
|
|
||||||
|
|
||||||
/* Do not bother attempting the download if the owner has left */
|
|
||||||
if (owner == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
guac_client* client = owner->client;
|
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
|
||||||
guac_rdp_fs* filesystem = rdp_client->filesystem;
|
|
||||||
|
|
||||||
/* Ignore download if filesystem has been unloaded */
|
|
||||||
if (filesystem == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Attempt to open requested file */
|
|
||||||
char* path = (char*) data;
|
|
||||||
int file_id = guac_rdp_fs_open(filesystem, path,
|
|
||||||
ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0);
|
|
||||||
|
|
||||||
/* If file opened successfully, start stream */
|
|
||||||
if (file_id >= 0) {
|
|
||||||
|
|
||||||
guac_rdp_stream* rdp_stream;
|
|
||||||
const char* basename;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
/* Associate stream with transfer status */
|
|
||||||
guac_stream* stream = guac_user_alloc_stream(owner);
|
|
||||||
stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream));
|
|
||||||
stream->ack_handler = guac_rdp_download_ack_handler;
|
|
||||||
rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM;
|
|
||||||
rdp_stream->download_status.file_id = file_id;
|
|
||||||
rdp_stream->download_status.offset = 0;
|
|
||||||
|
|
||||||
/* Get basename from absolute path */
|
|
||||||
i=0;
|
|
||||||
basename = path;
|
|
||||||
do {
|
|
||||||
|
|
||||||
c = path[i];
|
|
||||||
if (c == '/' || c == '\\')
|
|
||||||
basename = &(path[i+1]);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
|
|
||||||
} while (c != '\0');
|
|
||||||
|
|
||||||
guac_user_log(owner, GUAC_LOG_DEBUG, "%s: Initiating download "
|
|
||||||
"of \"%s\"", __func__, path);
|
|
||||||
|
|
||||||
/* Begin stream */
|
|
||||||
guac_protocol_send_file(owner->socket, stream,
|
|
||||||
"application/octet-stream", basename);
|
|
||||||
guac_socket_flush(owner->socket);
|
|
||||||
|
|
||||||
/* Download started successfully */
|
|
||||||
return stream;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Download failed */
|
|
||||||
guac_user_log(owner, GUAC_LOG_ERROR, "Unable to download \"%s\"", path);
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void guac_rdpdr_start_download(guac_rdpdr_device* device, char* path) {
|
|
||||||
|
|
||||||
guac_client* client = device->rdpdr->client;
|
|
||||||
|
|
||||||
/* Initiate download to the owner of the connection */
|
|
||||||
guac_client_for_owner(client, guac_rdpdr_download_to_owner, path);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler for events which deal with data transmitted over the RDPDR
|
|
||||||
* channel. This specific implementation of the event handler currently
|
|
||||||
* handles only the CHANNEL_EVENT_DATA_RECEIVED event, delegating actual
|
|
||||||
* handling of that event to guac_rdpdr_process_receive().
|
|
||||||
*
|
|
||||||
* The FreeRDP requirements for this function follow those of the
|
|
||||||
* VirtualChannelOpenEventEx callback defined within Microsoft's RDP API:
|
|
||||||
*
|
|
||||||
* https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29
|
|
||||||
*
|
|
||||||
* @param user_param
|
|
||||||
* The pointer to arbitrary data originally passed via the first parameter
|
|
||||||
* of the pVirtualChannelInitEx() function call when the associated channel
|
|
||||||
* was initialized. The pVirtualChannelInitEx() function is exposed within
|
|
||||||
* the channel entry points structure.
|
|
||||||
*
|
|
||||||
* @param open_handle
|
|
||||||
* The handle which identifies the channel itself, typically referred to
|
|
||||||
* within the FreeRDP source as OpenHandle.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* An integer representing the event that should be handled. This will be
|
|
||||||
* either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or
|
|
||||||
* CHANNEL_EVENT_WRITE_COMPLETE.
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value
|
|
||||||
* passed as user data to pVirtualChannelWriteEx() for
|
|
||||||
* CHANNEL_EVENT_WRITE_* events (note that user data for
|
|
||||||
* pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL
|
|
||||||
* or a wStream containing the data written).
|
|
||||||
*
|
|
||||||
* @param data_length
|
|
||||||
* The number of bytes of event-specific data.
|
|
||||||
*
|
|
||||||
* @param total_length
|
|
||||||
* The total number of bytes written to the RDP server in a single write
|
|
||||||
* operation.
|
|
||||||
*
|
|
||||||
* NOTE: The meaning of total_length is unclear. The above description was
|
|
||||||
* written mainly through referencing the documentation in MSDN. Real-world
|
|
||||||
* use will need to be consulted, likely within the FreeRDP source, before
|
|
||||||
* this value can be reliably used. The current implementation of this
|
|
||||||
* handler ignores this parameter.
|
|
||||||
*
|
|
||||||
* @param data_flags
|
|
||||||
* The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to
|
|
||||||
* the data received. This value is relevant only to
|
|
||||||
* CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST,
|
|
||||||
* CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE
|
|
||||||
* is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and
|
|
||||||
* CHANNEL_FLAG_LAST.
|
|
||||||
*/
|
|
||||||
static VOID guac_rdpdr_handle_open_event(LPVOID user_param,
|
|
||||||
DWORD open_handle, UINT event, LPVOID data, UINT32 data_length,
|
|
||||||
UINT32 total_length, UINT32 data_flags) {
|
|
||||||
|
|
||||||
/* Ignore all events except for received data */
|
|
||||||
if (event != CHANNEL_EVENT_DATA_RECEIVED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
guac_rdpdr* rdpdr = (guac_rdpdr*) user_param;
|
|
||||||
|
|
||||||
/* Validate relevant handle matches that of the RDPDR channel */
|
|
||||||
if (open_handle != rdpdr->open_handle) {
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_WARNING, "%i bytes of data "
|
|
||||||
"received from within the remote desktop session for the "
|
|
||||||
"RDPDR channel are being dropped because the relevant open "
|
|
||||||
"handle (0x%X) does not match the open handle of RDPDR "
|
|
||||||
"(0x%X).", data_length, rdpdr->channel_def.name, open_handle,
|
|
||||||
rdpdr->open_handle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wStream* input_stream = Stream_New(data, data_length);
|
|
||||||
guac_rdpdr_process_receive(rdpdr, input_stream);
|
|
||||||
Stream_Free(input_stream, FALSE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a CHANNEL_EVENT_CONNECTED event, completing the
|
|
||||||
* connection/initialization process of the RDPDR channel.
|
|
||||||
*
|
|
||||||
* @param rdpdr
|
|
||||||
* The guac_rdpdr structure representing the RDPDR channel.
|
|
||||||
*/
|
|
||||||
static void guac_rdpdr_process_connect(guac_rdpdr* rdpdr) {
|
|
||||||
|
|
||||||
/* Get data from client */
|
|
||||||
guac_client* client = rdpdr->client;
|
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
|
||||||
|
|
||||||
/* Open FreeRDP side of connected channel */
|
|
||||||
UINT32 open_status =
|
|
||||||
rdpdr->entry_points.pVirtualChannelOpenEx(rdpdr->init_handle,
|
|
||||||
&rdpdr->open_handle, rdpdr->channel_def.name,
|
|
||||||
guac_rdpdr_handle_open_event);
|
|
||||||
|
|
||||||
/* Warn if the channel cannot be opened after all */
|
|
||||||
if (open_status != CHANNEL_RC_OK) {
|
|
||||||
guac_client_log(client, GUAC_LOG_WARNING, "RDPDR channel could not be "
|
|
||||||
"opened: %s (error %i)", WTSErrorToString(open_status),
|
|
||||||
open_status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register printer if enabled */
|
|
||||||
if (rdp_client->settings->printing_enabled)
|
|
||||||
guac_rdpdr_register_printer(rdpdr, rdp_client->settings->printer_name);
|
|
||||||
|
|
||||||
/* Register drive if enabled */
|
|
||||||
if (rdp_client->settings->drive_enabled)
|
|
||||||
guac_rdpdr_register_fs(rdpdr, rdp_client->settings->drive_name);
|
|
||||||
|
|
||||||
/* Log that printing, etc. has been loaded */
|
|
||||||
guac_client_log(client, GUAC_LOG_INFO, "RDPDR channel connected.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated
|
|
||||||
* with the RDPDR channel.
|
|
||||||
*
|
|
||||||
* @param rdpdr
|
|
||||||
* The guac_rdpdr structure representing the RDPDR channel.
|
|
||||||
*/
|
|
||||||
static void guac_rdpdr_process_terminate(guac_rdpdr* rdpdr) {
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<rdpdr->devices_registered; i++) {
|
|
||||||
guac_rdpdr_device* device = &(rdpdr->devices[i]);
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Unloading device %i (%s)",
|
|
||||||
device->device_id, device->device_name);
|
|
||||||
device->free_handler(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "RDPDR channel disconnected.");
|
|
||||||
free(rdpdr);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler for events which deal with the overall lifecycle of the RDPDR
|
|
||||||
* channel. This specific implementation of the event handler currently
|
|
||||||
* handles only CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events,
|
|
||||||
* delegating actual handling of those events to guac_rdpdr_process_connect()
|
|
||||||
* and guac_rdpdr_process_terminate() respectively.
|
|
||||||
*
|
|
||||||
* The FreeRDP requirements for this function follow those of the
|
|
||||||
* VirtualChannelInitEventEx callback defined within Microsoft's RDP API:
|
|
||||||
*
|
|
||||||
* https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29
|
|
||||||
*
|
|
||||||
* @param user_param
|
|
||||||
* The pointer to arbitrary data originally passed via the first parameter
|
|
||||||
* of the pVirtualChannelInitEx() function call when the associated channel
|
|
||||||
* was initialized. The pVirtualChannelInitEx() function is exposed within
|
|
||||||
* the channel entry points structure.
|
|
||||||
*
|
|
||||||
* @param init_handle
|
|
||||||
* The handle which identifies the client connection, typically referred to
|
|
||||||
* within the FreeRDP source as pInitHandle.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* An integer representing the event that should be handled. This will be
|
|
||||||
* either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED,
|
|
||||||
* CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or
|
|
||||||
* CHANNEL_EVENT_V1_CONNECTED.
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which
|
|
||||||
* case this is a null-terminated string containing the name of the server.
|
|
||||||
*
|
|
||||||
* @param data_length
|
|
||||||
* The number of bytes of data, if any.
|
|
||||||
*/
|
|
||||||
static VOID guac_rdpdr_handle_init_event(LPVOID user_param,
|
|
||||||
LPVOID init_handle, UINT event, LPVOID data, UINT data_length) {
|
|
||||||
|
|
||||||
guac_rdpdr* rdpdr = (guac_rdpdr*) user_param;
|
|
||||||
|
|
||||||
/* Validate relevant handle matches that of the RDPDR channel */
|
|
||||||
if (init_handle != rdpdr->init_handle) {
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_WARNING, "An init event "
|
|
||||||
"(#%i) for the RDPDR channel has been dropped because the "
|
|
||||||
"relevant init handle (0x%X) does not match the init handle "
|
|
||||||
"of the RDPDR channel (0x%X).", event, init_handle,
|
|
||||||
rdpdr->init_handle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event) {
|
|
||||||
|
|
||||||
/* The RDPDR channel has been connected */
|
|
||||||
case CHANNEL_EVENT_CONNECTED:
|
|
||||||
guac_rdpdr_process_connect(rdpdr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* The RDPDR channel has disconnected and now must be cleaned up */
|
|
||||||
case CHANNEL_EVENT_TERMINATED:
|
|
||||||
guac_rdpdr_process_terminate(rdpdr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entry point for FreeRDP plugins. This function is automatically invoked when
|
|
||||||
* the plugin is loaded.
|
|
||||||
*
|
|
||||||
* @param entry_points
|
|
||||||
* Functions and data specific to the FreeRDP side of the virtual channel
|
|
||||||
* and plugin. This structure must be copied within implementation-specific
|
|
||||||
* storage such that the functions it references can be invoked when
|
|
||||||
* needed.
|
|
||||||
*
|
|
||||||
* @param init_handle
|
|
||||||
* The handle which identifies the client connection, typically referred to
|
|
||||||
* within the FreeRDP source as pInitHandle. This handle is also provided
|
|
||||||
* to the channel init event handler. The handle must eventually be used
|
|
||||||
* within the channel open event handler to obtain a handle to the channel
|
|
||||||
* itself.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* TRUE if the plugin has initialized successfully, FALSE otherwise.
|
|
||||||
*/
|
|
||||||
BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points,
|
|
||||||
PVOID init_handle) {
|
|
||||||
|
|
||||||
CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex =
|
|
||||||
(CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points;
|
|
||||||
|
|
||||||
/* Allocate plugin */
|
|
||||||
guac_rdpdr* rdpdr = (guac_rdpdr*) calloc(1, sizeof(guac_rdpdr));
|
|
||||||
|
|
||||||
/* Init channel def */
|
|
||||||
strcpy(rdpdr->channel_def.name, "rdpdr");
|
|
||||||
rdpdr->channel_def.options = CHANNEL_OPTION_INITIALIZED
|
|
||||||
| CHANNEL_OPTION_ENCRYPT_RDP
|
|
||||||
| CHANNEL_OPTION_COMPRESS_RDP;
|
|
||||||
|
|
||||||
/* Maintain reference to associated guac_client */
|
|
||||||
rdpdr->client = (guac_client*) entry_points_ex->pExtendedData;
|
|
||||||
|
|
||||||
/* No devices are connected initially */
|
|
||||||
rdpdr->devices_registered = 0;
|
|
||||||
|
|
||||||
/* Copy FreeRDP data into RDPSND structure for future reference */
|
|
||||||
rdpdr->entry_points = *entry_points_ex;
|
|
||||||
rdpdr->init_handle = init_handle;
|
|
||||||
|
|
||||||
/* Complete initialization */
|
|
||||||
if (rdpdr->entry_points.pVirtualChannelInitEx(rdpdr, rdpdr, init_handle,
|
|
||||||
&rdpdr->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
|
||||||
guac_rdpdr_handle_init_event) != CHANNEL_RC_OK) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GUAC_RDPDR_SERVICE_H
|
|
||||||
#define __GUAC_RDPDR_SERVICE_H
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <freerdp/svc.h>
|
|
||||||
#include <guacamole/client.h>
|
|
||||||
#include <winpr/stream.h>
|
|
||||||
#include <winpr/wtsapi.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum number of bytes to allow for a device read.
|
|
||||||
*/
|
|
||||||
#define GUAC_RDP_MAX_READ_BUFFER 4194304
|
|
||||||
|
|
||||||
typedef struct guac_rdpdr guac_rdpdr;
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
typedef void guac_rdpdr_device_announce_handler(guac_rdpdr_device* device, wStream* output_stream,
|
|
||||||
int device_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for device I/O requests.
|
|
||||||
*/
|
|
||||||
typedef void guac_rdpdr_device_iorequest_handler(guac_rdpdr_device* device,
|
|
||||||
wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for cleaning up the dynamically-allocated portions of a device.
|
|
||||||
*/
|
|
||||||
typedef void guac_rdpdr_device_free_handler(guac_rdpdr_device* device);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Arbitrary device forwarded over the RDPDR channel.
|
|
||||||
*/
|
|
||||||
struct guac_rdpdr_device {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The RDPDR plugin owning this device.
|
|
||||||
*/
|
|
||||||
guac_rdpdr* rdpdr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The ID assigned to this device by the RDPDR plugin.
|
|
||||||
*/
|
|
||||||
int device_id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Device name, used for logging and for passthrough to the
|
|
||||||
* server.
|
|
||||||
*/
|
|
||||||
const char* device_name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of RDPDR device that this represents.
|
|
||||||
*/
|
|
||||||
uint32_t device_type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The DOS name of the device. Max 8 bytes, including terminator.
|
|
||||||
*/
|
|
||||||
const char *dos_name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The stream that stores the RDPDR device announcement for this device.
|
|
||||||
*/
|
|
||||||
wStream* device_announce;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The length of the device_announce wStream.
|
|
||||||
*/
|
|
||||||
int device_announce_len;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler which should be called for every I/O request received.
|
|
||||||
*/
|
|
||||||
guac_rdpdr_device_iorequest_handler* iorequest_handler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler which should be called when the device is being freed.
|
|
||||||
*/
|
|
||||||
guac_rdpdr_device_free_handler* free_handler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Arbitrary data, used internally by the handlers for this device.
|
|
||||||
*/
|
|
||||||
void* data;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Structure representing the current state of the Guacamole RDPDR plugin for
|
|
||||||
* FreeRDP.
|
|
||||||
*/
|
|
||||||
struct guac_rdpdr {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reference to the client owning this instance of the RDPDR plugin.
|
|
||||||
*/
|
|
||||||
guac_client* client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The definition of this virtual channel (RDPDR).
|
|
||||||
*/
|
|
||||||
CHANNEL_DEF channel_def;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Functions and data specific to the FreeRDP side of the virtual channel
|
|
||||||
* and plugin.
|
|
||||||
*/
|
|
||||||
CHANNEL_ENTRY_POINTS_FREERDP_EX entry_points;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle which identifies the client connection, typically referred to
|
|
||||||
* within the FreeRDP source as pInitHandle. This handle is provided to the
|
|
||||||
* channel entry point and the channel init event handler. The handle must
|
|
||||||
* eventually be used within the channel open event handler to obtain a
|
|
||||||
* handle to the channel itself.
|
|
||||||
*/
|
|
||||||
PVOID init_handle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle which identifies the channel itself, typically referred to within
|
|
||||||
* the FreeRDP source as OpenHandle. This handle is obtained through a call
|
|
||||||
* to entry_points.pVirtualChannelOpenEx() in response to receiving a
|
|
||||||
* CHANNEL_EVENT_CONNECTED event via the init event handler.
|
|
||||||
*
|
|
||||||
* Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open
|
|
||||||
* event handler, and data is written through calls to
|
|
||||||
* entry_points.pVirtualChannelWriteEx().
|
|
||||||
*/
|
|
||||||
DWORD open_handle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of devices registered within the devices array.
|
|
||||||
*/
|
|
||||||
int devices_registered;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of registered devices.
|
|
||||||
*/
|
|
||||||
guac_rdpdr_device devices[8];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header
|
|
||||||
* used for virtually all responses.
|
|
||||||
*/
|
|
||||||
wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
|
|
||||||
int completion_id, int status, int size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Begins streaming the given file to the user via a Guacamole file stream.
|
|
||||||
*/
|
|
||||||
void guac_rdpdr_start_download(guac_rdpdr_device* device, char* path);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -20,24 +20,262 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
#include "rdp.h"
|
#include "rdp.h"
|
||||||
|
#include "rdp_fs.h"
|
||||||
|
#include "rdp_settings.h"
|
||||||
|
#include "rdp_stream.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
|
#include "rdpdr_fs_service.h"
|
||||||
|
#include "rdpdr_messages.h"
|
||||||
|
#include "rdpdr_printer.h"
|
||||||
|
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
|
#include <guacamole/protocol.h>
|
||||||
|
#include <guacamole/socket.h>
|
||||||
|
#include <guacamole/stream.h>
|
||||||
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void guac_rdpdr_process_receive(guac_rdp_common_svc* svc,
|
||||||
|
wStream* input_stream) {
|
||||||
|
|
||||||
|
int component;
|
||||||
|
int packet_id;
|
||||||
|
|
||||||
|
/* Read header */
|
||||||
|
Stream_Read_UINT16(input_stream, component);
|
||||||
|
Stream_Read_UINT16(input_stream, packet_id);
|
||||||
|
|
||||||
|
/* Core component */
|
||||||
|
if (component == RDPDR_CTYP_CORE) {
|
||||||
|
|
||||||
|
/* Dispatch handlers based on packet ID */
|
||||||
|
switch (packet_id) {
|
||||||
|
|
||||||
|
case PAKID_CORE_SERVER_ANNOUNCE:
|
||||||
|
guac_rdpdr_process_server_announce(svc, input_stream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAKID_CORE_CLIENTID_CONFIRM:
|
||||||
|
guac_rdpdr_process_clientid_confirm(svc, input_stream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAKID_CORE_DEVICE_REPLY:
|
||||||
|
guac_rdpdr_process_device_reply(svc, input_stream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAKID_CORE_DEVICE_IOREQUEST:
|
||||||
|
guac_rdpdr_process_device_iorequest(svc, input_stream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAKID_CORE_SERVER_CAPABILITY:
|
||||||
|
guac_rdpdr_process_server_capability(svc, input_stream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAKID_CORE_USER_LOGGEDON:
|
||||||
|
guac_rdpdr_process_user_loggedon(svc, input_stream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring "
|
||||||
|
"RDPDR core packet with unexpected ID: 0x%04x",
|
||||||
|
packet_id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end if core */
|
||||||
|
|
||||||
|
/* Printer component */
|
||||||
|
else if (component == RDPDR_CTYP_PRN) {
|
||||||
|
|
||||||
|
/* Dispatch handlers based on packet ID */
|
||||||
|
switch (packet_id) {
|
||||||
|
|
||||||
|
case PAKID_PRN_CACHE_DATA:
|
||||||
|
guac_rdpdr_process_prn_cache_data(svc, input_stream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAKID_PRN_USING_XPS:
|
||||||
|
guac_rdpdr_process_prn_using_xps(svc, input_stream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring RDPDR "
|
||||||
|
"printer packet with unexpected ID: 0x%04x",
|
||||||
|
packet_id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end if printer */
|
||||||
|
|
||||||
|
else
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring packet for "
|
||||||
|
"unknown RDPDR component: 0x%04x", component);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
|
||||||
|
int completion_id, int status, int size) {
|
||||||
|
|
||||||
|
wStream* output_stream = Stream_New(NULL, 16+size);
|
||||||
|
|
||||||
|
/* Write header */
|
||||||
|
Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
|
||||||
|
Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICE_IOCOMPLETION);
|
||||||
|
|
||||||
|
/* Write content */
|
||||||
|
Stream_Write_UINT32(output_stream, device->device_id);
|
||||||
|
Stream_Write_UINT32(output_stream, completion_id);
|
||||||
|
Stream_Write_UINT32(output_stream, status);
|
||||||
|
|
||||||
|
return output_stream;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked on the current connection owner (if any) when a file
|
||||||
|
* download is being initiated using the magic "Download" folder.
|
||||||
|
*
|
||||||
|
* @param owner
|
||||||
|
* The guac_user that is the owner of the connection, or NULL if the
|
||||||
|
* connection owner has left.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* The full absolute path to the file that should be downloaded.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The stream allocated for the file download, or NULL if the download has
|
||||||
|
* failed to start.
|
||||||
|
*/
|
||||||
|
static void* guac_rdpdr_download_to_owner(guac_user* owner, void* data) {
|
||||||
|
|
||||||
|
/* Do not bother attempting the download if the owner has left */
|
||||||
|
if (owner == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
guac_client* client = owner->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
guac_rdp_fs* filesystem = rdp_client->filesystem;
|
||||||
|
|
||||||
|
/* Ignore download if filesystem has been unloaded */
|
||||||
|
if (filesystem == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Attempt to open requested file */
|
||||||
|
char* path = (char*) data;
|
||||||
|
int file_id = guac_rdp_fs_open(filesystem, path,
|
||||||
|
ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0);
|
||||||
|
|
||||||
|
/* If file opened successfully, start stream */
|
||||||
|
if (file_id >= 0) {
|
||||||
|
|
||||||
|
guac_rdp_stream* rdp_stream;
|
||||||
|
const char* basename;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
/* Associate stream with transfer status */
|
||||||
|
guac_stream* stream = guac_user_alloc_stream(owner);
|
||||||
|
stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream));
|
||||||
|
stream->ack_handler = guac_rdp_download_ack_handler;
|
||||||
|
rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM;
|
||||||
|
rdp_stream->download_status.file_id = file_id;
|
||||||
|
rdp_stream->download_status.offset = 0;
|
||||||
|
|
||||||
|
/* Get basename from absolute path */
|
||||||
|
i=0;
|
||||||
|
basename = path;
|
||||||
|
do {
|
||||||
|
|
||||||
|
c = path[i];
|
||||||
|
if (c == '/' || c == '\\')
|
||||||
|
basename = &(path[i+1]);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
} while (c != '\0');
|
||||||
|
|
||||||
|
guac_user_log(owner, GUAC_LOG_DEBUG, "%s: Initiating download "
|
||||||
|
"of \"%s\"", __func__, path);
|
||||||
|
|
||||||
|
/* Begin stream */
|
||||||
|
guac_protocol_send_file(owner->socket, stream,
|
||||||
|
"application/octet-stream", basename);
|
||||||
|
guac_socket_flush(owner->socket);
|
||||||
|
|
||||||
|
/* Download started successfully */
|
||||||
|
return stream;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Download failed */
|
||||||
|
guac_user_log(owner, GUAC_LOG_ERROR, "Unable to download \"%s\"", path);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void guac_rdpdr_start_download(guac_rdp_common_svc* svc,
|
||||||
|
guac_rdpdr_device* device, char* path) {
|
||||||
|
|
||||||
|
guac_client* client = svc->client;
|
||||||
|
|
||||||
|
/* Initiate download to the owner of the connection */
|
||||||
|
guac_client_for_owner(client, guac_rdpdr_download_to_owner, path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void guac_rdpdr_process_connect(guac_rdp_common_svc* svc) {
|
||||||
|
|
||||||
|
/* Get data from client */
|
||||||
|
guac_client* client = svc->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
guac_rdpdr* rdpdr = (guac_rdpdr*) calloc(1, sizeof(guac_rdpdr));
|
||||||
|
svc->data = rdpdr;
|
||||||
|
|
||||||
|
/* Register printer if enabled */
|
||||||
|
if (rdp_client->settings->printing_enabled)
|
||||||
|
guac_rdpdr_register_printer(svc, rdp_client->settings->printer_name);
|
||||||
|
|
||||||
|
/* Register drive if enabled */
|
||||||
|
if (rdp_client->settings->drive_enabled)
|
||||||
|
guac_rdpdr_register_fs(svc, rdp_client->settings->drive_name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void guac_rdpdr_process_terminate(guac_rdp_common_svc* svc) {
|
||||||
|
|
||||||
|
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<rdpdr->devices_registered; i++) {
|
||||||
|
guac_rdpdr_device* device = &(rdpdr->devices[i]);
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unloading device %i "
|
||||||
|
"(%s)", device->device_id, device->device_name);
|
||||||
|
device->free_handler(svc, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(rdpdr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void guac_rdpdr_load_plugin(rdpContext* context) {
|
void guac_rdpdr_load_plugin(rdpContext* context) {
|
||||||
|
|
||||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||||
|
|
||||||
/* Load RDPDR plugin */
|
/* Load support for RDPDR */
|
||||||
if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "guacdr", client)) {
|
if (guac_rdp_common_svc_load_plugin(context, "rdpdr",
|
||||||
|
CHANNEL_OPTION_COMPRESS_RDP, guac_rdpdr_process_connect,
|
||||||
|
guac_rdpdr_process_receive, guac_rdpdr_process_terminate)) {
|
||||||
guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPDR "
|
guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPDR "
|
||||||
"channel (device redirection) could not be loaded. Drive "
|
"channel (device redirection) could not be loaded. Drive "
|
||||||
"redirection and printing will not work. Sound MAY not work.");
|
"redirection and printing will not work. Sound MAY not work.");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guac_client_log(client, GUAC_LOG_DEBUG, "Support for RDPDR (device "
|
|
||||||
"redirection) registered. Awaiting channel connection.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,121 @@
|
|||||||
#define GUAC_RDP_RDPDR_H
|
#define GUAC_RDP_RDPDR_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "common-svc.h"
|
||||||
|
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
#include <guacamole/client.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of bytes to allow for a device read.
|
||||||
|
*/
|
||||||
|
#define GUAC_RDP_MAX_READ_BUFFER 4194304
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arbitrary device forwarded over the RDPDR channel.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
typedef void guac_rdpdr_device_announce_handler(guac_rdp_common_svc* svc,
|
||||||
|
guac_rdpdr_device* device, wStream* output_stream, int device_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for device I/O requests.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for cleaning up the dynamically-allocated portions of a device.
|
||||||
|
*/
|
||||||
|
typedef void guac_rdpdr_device_free_handler(guac_rdp_common_svc* svc,
|
||||||
|
guac_rdpdr_device* device);
|
||||||
|
|
||||||
|
struct guac_rdpdr_device {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID assigned to this device by the RDPDR plugin.
|
||||||
|
*/
|
||||||
|
int device_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Device name, used for logging and for passthrough to the
|
||||||
|
* server.
|
||||||
|
*/
|
||||||
|
const char* device_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of RDPDR device that this represents.
|
||||||
|
*/
|
||||||
|
uint32_t device_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DOS name of the device. Max 8 bytes, including terminator.
|
||||||
|
*/
|
||||||
|
const char *dos_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The stream that stores the RDPDR device announcement for this device.
|
||||||
|
*/
|
||||||
|
wStream* device_announce;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The length of the device_announce wStream.
|
||||||
|
*/
|
||||||
|
int device_announce_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler which should be called for every I/O request received.
|
||||||
|
*/
|
||||||
|
guac_rdpdr_device_iorequest_handler* iorequest_handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler which should be called when the device is being freed.
|
||||||
|
*/
|
||||||
|
guac_rdpdr_device_free_handler* free_handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arbitrary data, used internally by the handlers for this device.
|
||||||
|
*/
|
||||||
|
void* data;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure representing the current state of the Guacamole RDPDR plugin for
|
||||||
|
* FreeRDP.
|
||||||
|
*/
|
||||||
|
typedef struct guac_rdpdr {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of devices registered within the devices array.
|
||||||
|
*/
|
||||||
|
int devices_registered;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of registered devices.
|
||||||
|
*/
|
||||||
|
guac_rdpdr_device devices[8];
|
||||||
|
|
||||||
|
} guac_rdpdr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header
|
||||||
|
* used for virtually all responses.
|
||||||
|
*/
|
||||||
|
wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
|
||||||
|
int completion_id, int status, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begins streaming the given file to the user via a Guacamole file stream.
|
||||||
|
*/
|
||||||
|
void guac_rdpdr_start_download(guac_rdp_common_svc* svc,
|
||||||
|
guac_rdpdr_device* device, char* path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes device redirection support (file transfer, printing, etc.) for
|
* Initializes device redirection support (file transfer, printing, etc.) for
|
||||||
@ -36,5 +151,23 @@
|
|||||||
*/
|
*/
|
||||||
void guac_rdpdr_load_plugin(rdpContext* context);
|
void guac_rdpdr_load_plugin(rdpContext* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler which is invoked when the RDPDR channel is connected to the RDP
|
||||||
|
* server.
|
||||||
|
*/
|
||||||
|
guac_rdp_common_svc_connect_handler guac_rdpdr_process_connect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler which is invoked when the RDPDR channel has received data from the
|
||||||
|
* RDP server.
|
||||||
|
*/
|
||||||
|
guac_rdp_common_svc_receive_handler guac_rdpdr_process_receive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler which is invoked when the RDPDR channel has disconnected and is
|
||||||
|
* about to be freed.
|
||||||
|
*/
|
||||||
|
guac_rdp_common_svc_terminate_handler guac_rdpdr_process_terminate;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -18,13 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_fs_messages_dir_info.h"
|
#include "rdpdr_fs_messages_dir_info.h"
|
||||||
#include "rdpdr_fs_messages_file_info.h"
|
#include "rdpdr_fs_messages_file_info.h"
|
||||||
#include "rdpdr_fs_messages.h"
|
#include "rdpdr_fs_messages.h"
|
||||||
#include "rdpdr_fs_messages_vol_info.h"
|
#include "rdpdr_fs_messages_vol_info.h"
|
||||||
#include "rdpdr_messages.h"
|
#include "rdpdr_messages.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
#include "rdp_fs.h"
|
#include "rdp_fs.h"
|
||||||
#include "rdp_status.h"
|
#include "rdp_status.h"
|
||||||
#include "unicode.h"
|
#include "unicode.h"
|
||||||
@ -38,8 +37,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
int file_id;
|
int file_id;
|
||||||
@ -66,7 +65,7 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
|
|||||||
desired_access, file_attributes,
|
desired_access, file_attributes,
|
||||||
create_disposition, create_options);
|
create_disposition, create_options);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] "
|
"%s: [file_id=%i] "
|
||||||
"desired_access=0x%x, file_attributes=0x%x, "
|
"desired_access=0x%x, file_attributes=0x%x, "
|
||||||
"create_disposition=0x%x, create_options=0x%x, path=\"%s\"",
|
"create_disposition=0x%x, create_options=0x%x, path=\"%s\"",
|
||||||
@ -76,7 +75,7 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
|
|||||||
|
|
||||||
/* If an error occurred, notify server */
|
/* If an error occurred, notify server */
|
||||||
if (file_id < 0) {
|
if (file_id < 0) {
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_ERROR,
|
guac_client_log(svc->client, GUAC_LOG_ERROR,
|
||||||
"File open refused (%i): \"%s\"", file_id, path);
|
"File open refused (%i): \"%s\"", file_id, path);
|
||||||
|
|
||||||
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
output_stream = guac_rdpdr_new_io_completion(device, completion_id,
|
||||||
@ -109,14 +108,13 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_read(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
UINT32 length;
|
UINT32 length;
|
||||||
UINT64 offset;
|
UINT64 offset;
|
||||||
@ -129,7 +127,7 @@ void guac_rdpdr_fs_process_read(guac_rdpdr_device* device,
|
|||||||
Stream_Read_UINT32(input_stream, length);
|
Stream_Read_UINT32(input_stream, length);
|
||||||
Stream_Read_UINT64(input_stream, offset);
|
Stream_Read_UINT64(input_stream, offset);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] length=%i, offset=%" PRIu64,
|
"%s: [file_id=%i] length=%i, offset=%" PRIu64,
|
||||||
__func__, file_id, length, (uint64_t) offset);
|
__func__, file_id, length, (uint64_t) offset);
|
||||||
|
|
||||||
@ -159,15 +157,14 @@ void guac_rdpdr_fs_process_read(guac_rdpdr_device* device,
|
|||||||
Stream_Write(output_stream, buffer, bytes_read); /* ReadData */
|
Stream_Write(output_stream, buffer, bytes_read); /* ReadData */
|
||||||
}
|
}
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_write(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
UINT32 length;
|
UINT32 length;
|
||||||
UINT64 offset;
|
UINT64 offset;
|
||||||
@ -180,7 +177,7 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device,
|
|||||||
Stream_Read_UINT64(input_stream, offset);
|
Stream_Read_UINT64(input_stream, offset);
|
||||||
Stream_Seek(input_stream, 20); /* Padding */
|
Stream_Seek(input_stream, 20); /* Padding */
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] length=%i, offset=%" PRIu64,
|
"%s: [file_id=%i] length=%i, offset=%" PRIu64,
|
||||||
__func__, file_id, length, (uint64_t) offset);
|
__func__, file_id, length, (uint64_t) offset);
|
||||||
|
|
||||||
@ -204,19 +201,18 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device,
|
|||||||
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
||||||
}
|
}
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_close(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
guac_rdp_fs_file* file;
|
guac_rdp_fs_file* file;
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -228,7 +224,7 @@ void guac_rdpdr_fs_process_close(guac_rdpdr_device* device,
|
|||||||
/* If file was written to, and it's in the \Download folder, start stream */
|
/* If file was written to, and it's in the \Download folder, start stream */
|
||||||
if (file->bytes_written > 0 &&
|
if (file->bytes_written > 0 &&
|
||||||
strncmp(file->absolute_path, "\\Download\\", 10) == 0) {
|
strncmp(file->absolute_path, "\\Download\\", 10) == 0) {
|
||||||
guac_rdpdr_start_download(device, file->absolute_path);
|
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, file_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,14 +235,13 @@ void guac_rdpdr_fs_process_close(guac_rdpdr_device* device,
|
|||||||
STATUS_SUCCESS, 4);
|
STATUS_SUCCESS, 4);
|
||||||
Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */
|
Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_volume_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
int fs_information_class;
|
int fs_information_class;
|
||||||
|
|
||||||
@ -256,39 +251,40 @@ void guac_rdpdr_fs_process_volume_info(guac_rdpdr_device* device, wStream* input
|
|||||||
switch (fs_information_class) {
|
switch (fs_information_class) {
|
||||||
|
|
||||||
case FileFsVolumeInformation:
|
case FileFsVolumeInformation:
|
||||||
guac_rdpdr_fs_process_query_volume_info(device, input_stream,
|
guac_rdpdr_fs_process_query_volume_info(svc, device, input_stream,
|
||||||
file_id, completion_id);
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsSizeInformation:
|
case FileFsSizeInformation:
|
||||||
guac_rdpdr_fs_process_query_size_info(device, input_stream,
|
guac_rdpdr_fs_process_query_size_info(svc, device, input_stream,
|
||||||
file_id, completion_id);
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsDeviceInformation:
|
case FileFsDeviceInformation:
|
||||||
guac_rdpdr_fs_process_query_device_info(device, input_stream,
|
guac_rdpdr_fs_process_query_device_info(svc, device, input_stream,
|
||||||
file_id, completion_id);
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsAttributeInformation:
|
case FileFsAttributeInformation:
|
||||||
guac_rdpdr_fs_process_query_attribute_info(device, input_stream,
|
guac_rdpdr_fs_process_query_attribute_info(svc, device,
|
||||||
file_id, completion_id);
|
input_stream, file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsFullSizeInformation:
|
case FileFsFullSizeInformation:
|
||||||
guac_rdpdr_fs_process_query_full_size_info(device, input_stream,
|
guac_rdpdr_fs_process_query_full_size_info(svc, device,
|
||||||
file_id, completion_id);
|
input_stream, file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_INFO,
|
guac_client_log(svc->client, GUAC_LOG_INFO,
|
||||||
"Unknown volume information class: 0x%x", fs_information_class);
|
"Unknown volume information class: 0x%x", fs_information_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_file_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
int fs_information_class;
|
int fs_information_class;
|
||||||
|
|
||||||
@ -298,45 +294,45 @@ void guac_rdpdr_fs_process_file_info(guac_rdpdr_device* device, wStream* input_s
|
|||||||
switch (fs_information_class) {
|
switch (fs_information_class) {
|
||||||
|
|
||||||
case FileBasicInformation:
|
case FileBasicInformation:
|
||||||
guac_rdpdr_fs_process_query_basic_info(device, input_stream,
|
guac_rdpdr_fs_process_query_basic_info(svc, device, input_stream,
|
||||||
file_id, completion_id);
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileStandardInformation:
|
case FileStandardInformation:
|
||||||
guac_rdpdr_fs_process_query_standard_info(device, input_stream,
|
guac_rdpdr_fs_process_query_standard_info(svc, device,
|
||||||
file_id, completion_id);
|
input_stream, file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileAttributeTagInformation:
|
case FileAttributeTagInformation:
|
||||||
guac_rdpdr_fs_process_query_attribute_tag_info(device, input_stream,
|
guac_rdpdr_fs_process_query_attribute_tag_info(svc, device,
|
||||||
file_id, completion_id);
|
input_stream, file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_INFO,
|
guac_client_log(svc->client, GUAC_LOG_INFO,
|
||||||
"Unknown file information class: 0x%x", fs_information_class);
|
"Unknown file information class: 0x%x", fs_information_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_set_volume_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_NOT_SUPPORTED, 0);
|
completion_id, STATUS_NOT_SUPPORTED, 0);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] Set volume info not supported",
|
"%s: [file_id=%i] Set volume info not supported",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_set_file_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
int fs_information_class;
|
int fs_information_class;
|
||||||
int length;
|
int length;
|
||||||
@ -349,68 +345,69 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdpdr_device* device,
|
|||||||
switch (fs_information_class) {
|
switch (fs_information_class) {
|
||||||
|
|
||||||
case FileBasicInformation:
|
case FileBasicInformation:
|
||||||
guac_rdpdr_fs_process_set_basic_info(device, input_stream,
|
guac_rdpdr_fs_process_set_basic_info(svc, device, input_stream,
|
||||||
file_id, completion_id, length);
|
file_id, completion_id, length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileEndOfFileInformation:
|
case FileEndOfFileInformation:
|
||||||
guac_rdpdr_fs_process_set_end_of_file_info(device, input_stream,
|
guac_rdpdr_fs_process_set_end_of_file_info(svc, device,
|
||||||
file_id, completion_id, length);
|
input_stream, file_id, completion_id, length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileDispositionInformation:
|
case FileDispositionInformation:
|
||||||
guac_rdpdr_fs_process_set_disposition_info(device, input_stream,
|
guac_rdpdr_fs_process_set_disposition_info(svc, device,
|
||||||
file_id, completion_id, length);
|
input_stream, file_id, completion_id, length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileRenameInformation:
|
case FileRenameInformation:
|
||||||
guac_rdpdr_fs_process_set_rename_info(device, input_stream,
|
guac_rdpdr_fs_process_set_rename_info(svc, device, input_stream,
|
||||||
file_id, completion_id, length);
|
file_id, completion_id, length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileAllocationInformation:
|
case FileAllocationInformation:
|
||||||
guac_rdpdr_fs_process_set_allocation_info(device, input_stream,
|
guac_rdpdr_fs_process_set_allocation_info(svc, device,
|
||||||
file_id, completion_id, length);
|
input_stream, file_id, completion_id, length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_INFO,
|
guac_client_log(svc->client, GUAC_LOG_INFO,
|
||||||
"Unknown file information class: 0x%x",
|
"Unknown file information class: 0x%x",
|
||||||
fs_information_class);
|
fs_information_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_device_control(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_INVALID_PARAMETER, 4);
|
completion_id, STATUS_INVALID_PARAMETER, 4);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] IGNORED",
|
"%s: [file_id=%i] IGNORED",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
/* No content for now */
|
/* No content for now */
|
||||||
Stream_Write_UINT32(output_stream, 0);
|
Stream_Write_UINT32(output_stream, 0);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_notify_change_directory(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] Not implemented",
|
"%s: [file_id=%i] Not implemented",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
|
|
||||||
@ -441,7 +438,7 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] initial_query=%i, dir_pattern=\"%s\"",
|
"%s: [file_id=%i] initial_query=%i, dir_pattern=\"%s\"",
|
||||||
__func__, file_id, initial_query, file->dir_pattern);
|
__func__, file_id, initial_query, file->dir_pattern);
|
||||||
|
|
||||||
@ -470,27 +467,29 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i
|
|||||||
switch (fs_information_class) {
|
switch (fs_information_class) {
|
||||||
|
|
||||||
case FileDirectoryInformation:
|
case FileDirectoryInformation:
|
||||||
guac_rdpdr_fs_process_query_directory_info(device,
|
guac_rdpdr_fs_process_query_directory_info(svc, device,
|
||||||
entry_name, entry_file_id, completion_id);
|
entry_name, entry_file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFullDirectoryInformation:
|
case FileFullDirectoryInformation:
|
||||||
guac_rdpdr_fs_process_query_full_directory_info(device,
|
guac_rdpdr_fs_process_query_full_directory_info(svc,
|
||||||
entry_name, entry_file_id, completion_id);
|
device, entry_name, entry_file_id,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileBothDirectoryInformation:
|
case FileBothDirectoryInformation:
|
||||||
guac_rdpdr_fs_process_query_both_directory_info(device,
|
guac_rdpdr_fs_process_query_both_directory_info(svc,
|
||||||
entry_name, entry_file_id, completion_id);
|
device, entry_name, entry_file_id,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileNamesInformation:
|
case FileNamesInformation:
|
||||||
guac_rdpdr_fs_process_query_names_info(device,
|
guac_rdpdr_fs_process_query_names_info(svc, device,
|
||||||
entry_name, entry_file_id, completion_id);
|
entry_name, entry_file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_INFO,
|
guac_client_log(svc->client, GUAC_LOG_INFO,
|
||||||
"Unknown dir information class: 0x%x",
|
"Unknown dir information class: 0x%x",
|
||||||
fs_information_class);
|
fs_information_class);
|
||||||
}
|
}
|
||||||
@ -512,27 +511,24 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i
|
|||||||
Stream_Write_UINT32(output_stream, 0); /* Length */
|
Stream_Write_UINT32(output_stream, 0); /* Length */
|
||||||
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_lock_control(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_NOT_SUPPORTED, 5);
|
completion_id, STATUS_NOT_SUPPORTED, 5);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] Lock not supported",
|
"%s: [file_id=%i] Lock not supported",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
Stream_Zero(output_stream, 5); /* Padding */
|
Stream_Zero(output_stream, 5); /* Padding */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -18,8 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GUAC_RDPDR_FS_MESSAGES_H
|
#ifndef GUAC_RDPDR_FS_MESSAGES_H
|
||||||
#define __GUAC_RDPDR_FS_MESSAGES_H
|
#define GUAC_RDPDR_FS_MESSAGES_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handlers for core drive I/O requests. Requests handled here may be simple
|
* Handlers for core drive I/O requests. Requests handled here may be simple
|
||||||
@ -30,8 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
@ -39,33 +38,37 @@
|
|||||||
* Handles a Server Create Drive Request. Despite its name, this request opens
|
* Handles a Server Create Drive Request. Despite its name, this request opens
|
||||||
* a file.
|
* a file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Close Drive Reqiest. This request closes an open file.
|
* Handles a Server Close Drive Reqiest. This request closes an open file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_close(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Read Request. This request reads from a file.
|
* Handles a Server Drive Read Request. This request reads from a file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_read(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Write Request. This request writes to a file.
|
* Handles a Server Drive Write Request. This request writes to a file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_write(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Control Request. This request handles one of any
|
* Handles a Server Drive Control Request. This request handles one of any
|
||||||
* number of Windows FSCTL_* control functions.
|
* number of Windows FSCTL_* control functions.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_device_control(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Query Volume Information Request. This request
|
* Handles a Server Drive Query Volume Information Request. This request
|
||||||
@ -73,53 +76,60 @@ void guac_rdpdr_fs_process_device_control(guac_rdpdr_device* device, wStream* in
|
|||||||
* has several query types which have their own handlers defined in a
|
* has several query types which have their own handlers defined in a
|
||||||
* separate file.
|
* separate file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_volume_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Set Volume Information Request. Currently, this
|
* Handles a Server Drive Set Volume Information Request. Currently, this
|
||||||
* RDPDR implementation does not support setting of volume information.
|
* RDPDR implementation does not support setting of volume information.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_set_volume_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Query Information Request. This request queries
|
* Handles a Server Drive Query Information Request. This request queries
|
||||||
* information about a specific file. This request has several query types
|
* information about a specific file. This request has several query types
|
||||||
* which have their own handlers defined in a separate file.
|
* which have their own handlers defined in a separate file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_file_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Set Information Request. This request sets
|
* Handles a Server Drive Set Information Request. This request sets
|
||||||
* information about a specific file. Currently, this RDPDR implementation does
|
* information about a specific file. Currently, this RDPDR implementation does
|
||||||
* not support setting of file information.
|
* not support setting of file information.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_set_file_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Query Directory Request. This request queries
|
* Handles a Server Drive Query Directory Request. This request queries
|
||||||
* information about a specific directory. This request has several query types
|
* information about a specific directory. This request has several query types
|
||||||
* which have their own handlers defined in a separate file.
|
* which have their own handlers defined in a separate file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive NotifyChange Directory Request. This request requests
|
* Handles a Server Drive NotifyChange Directory Request. This request requests
|
||||||
* directory change notification.
|
* directory change notification.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_notify_change_directory(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a Server Drive Lock Control Request. This request locks or unlocks
|
* Handles a Server Drive Lock Control Request. This request locks or unlocks
|
||||||
* portions of a file.
|
* portions of a file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_lock_control(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -18,8 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
#include "rdp_fs.h"
|
#include "rdp_fs.h"
|
||||||
#include "rdp_status.h"
|
#include "rdp_status.h"
|
||||||
#include "unicode.h"
|
#include "unicode.h"
|
||||||
@ -29,8 +28,9 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc,
|
||||||
const char* entry_name, int file_id, int completion_id) {
|
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
guac_rdp_fs_file* file;
|
guac_rdp_fs_file* file;
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device,
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i (entry_name=\"%s\")]",
|
"%s: [file_id=%i (entry_name=\"%s\")]",
|
||||||
__func__, file_id, entry_name);
|
__func__, file_id, entry_name);
|
||||||
|
|
||||||
@ -71,14 +71,13 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device,
|
|||||||
Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */
|
Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */
|
||||||
Stream_Write(output_stream, "\0\0", 2);
|
Stream_Write(output_stream, "\0\0", 2);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc,
|
||||||
const char* entry_name, int file_id, int completion_id) {
|
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
guac_rdp_fs_file* file;
|
guac_rdp_fs_file* file;
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device,
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i (entry_name=\"%s\")]",
|
"%s: [file_id=%i (entry_name=\"%s\")]",
|
||||||
__func__, file_id, entry_name);
|
__func__, file_id, entry_name);
|
||||||
|
|
||||||
@ -120,14 +119,13 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device,
|
|||||||
Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */
|
Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */
|
||||||
Stream_Write(output_stream, "\0\0", 2);
|
Stream_Write(output_stream, "\0\0", 2);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc,
|
||||||
const char* entry_name, int file_id, int completion_id) {
|
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
guac_rdp_fs_file* file;
|
guac_rdp_fs_file* file;
|
||||||
|
|
||||||
@ -144,7 +142,7 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device,
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i (entry_name=\"%s\")]",
|
"%s: [file_id=%i (entry_name=\"%s\")]",
|
||||||
__func__, file_id, entry_name);
|
__func__, file_id, entry_name);
|
||||||
|
|
||||||
@ -173,14 +171,13 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device,
|
|||||||
Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */
|
Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */
|
||||||
Stream_Write(output_stream, "\0\0", 2);
|
Stream_Write(output_stream, "\0\0", 2);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc,
|
||||||
const char* entry_name, int file_id, int completion_id) {
|
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
guac_rdp_fs_file* file;
|
guac_rdp_fs_file* file;
|
||||||
|
|
||||||
@ -197,7 +194,7 @@ void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device,
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i (entry_name=\"%s\")]",
|
"%s: [file_id=%i (entry_name=\"%s\")]",
|
||||||
__func__, file_id, entry_name);
|
__func__, file_id, entry_name);
|
||||||
|
|
||||||
@ -213,9 +210,7 @@ void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device,
|
|||||||
Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */
|
Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */
|
||||||
Stream_Write(output_stream, "\0\0", 2);
|
Stream_Write(output_stream, "\0\0", 2);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -18,8 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
|
#ifndef GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
|
||||||
#define __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
|
#define GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handlers for directory queries received over the RDPDR channel via the
|
* Handlers for directory queries received over the RDPDR channel via the
|
||||||
@ -30,8 +30,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "common-svc.h"
|
||||||
#include "rdpdr_service.h"
|
#include "rdpdr.h"
|
||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
@ -40,31 +40,35 @@
|
|||||||
* documentation this is "defined as the file's name, time stamp, and size, or its
|
* documentation this is "defined as the file's name, time stamp, and size, or its
|
||||||
* attributes."
|
* attributes."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc,
|
||||||
const char* entry_name, int file_id, int completion_id);
|
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query request for FileFullDirectoryInformation. From the
|
* Processes a query request for FileFullDirectoryInformation. From the
|
||||||
* documentation, this is "defined as all the basic information, plus extended
|
* documentation, this is "defined as all the basic information, plus extended
|
||||||
* attribute size."
|
* attribute size."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc,
|
||||||
const char* entry_name, int file_id, int completion_id);
|
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query request for FileBothDirectoryInformation. From the
|
* Processes a query request for FileBothDirectoryInformation. From the
|
||||||
* documentation, this absurdly-named request is "basic information plus
|
* documentation, this absurdly-named request is "basic information plus
|
||||||
* extended attribute size and short name about a file or directory."
|
* extended attribute size and short name about a file or directory."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc,
|
||||||
const char* entry_name, int file_id, int completion_id);
|
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query request for FileNamesInformation. From the documentation,
|
* Processes a query request for FileNamesInformation. From the documentation,
|
||||||
* this is "detailed information on the names of files in a directory."
|
* this is "detailed information on the names of files in a directory."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc,
|
||||||
const char* entry_name, int file_id, int completion_id);
|
guac_rdpdr_device* device, const char* entry_name, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -18,8 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
#include "rdp_fs.h"
|
#include "rdp_fs.h"
|
||||||
#include "rdp_status.h"
|
#include "rdp_status.h"
|
||||||
#include "unicode.h"
|
#include "unicode.h"
|
||||||
@ -31,8 +30,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
guac_rdp_fs_file* file;
|
guac_rdp_fs_file* file;
|
||||||
@ -42,7 +42,7 @@ void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream*
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -58,14 +58,13 @@ void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream*
|
|||||||
|
|
||||||
/* Reserved field must not be sent */
|
/* Reserved field must not be sent */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
guac_rdp_fs_file* file;
|
guac_rdp_fs_file* file;
|
||||||
@ -76,7 +75,7 @@ void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStrea
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -95,14 +94,13 @@ void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStrea
|
|||||||
|
|
||||||
/* Reserved field must not be sent */
|
/* Reserved field must not be sent */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
guac_rdp_fs_file* file;
|
guac_rdp_fs_file* file;
|
||||||
@ -112,7 +110,7 @@ void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device,
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -125,14 +123,13 @@ void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device,
|
|||||||
|
|
||||||
/* Reserved field must not be sent */
|
/* Reserved field must not be sent */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length) {
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
int filename_length;
|
int filename_length;
|
||||||
@ -148,7 +145,7 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device,
|
|||||||
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2,
|
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2,
|
||||||
destination_path, sizeof(destination_path));
|
destination_path, sizeof(destination_path));
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] destination_path=\"%s\"",
|
"%s: [file_id=%i] destination_path=\"%s\"",
|
||||||
__func__, file_id, destination_path);
|
__func__, file_id, destination_path);
|
||||||
|
|
||||||
@ -163,7 +160,7 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Initiate download, pretend move succeeded */
|
/* Initiate download, pretend move succeeded */
|
||||||
guac_rdpdr_start_download(device, file->absolute_path);
|
guac_rdpdr_start_download(svc, device, file->absolute_path);
|
||||||
output_stream = guac_rdpdr_new_io_completion(device,
|
output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_SUCCESS, 4);
|
completion_id, STATUS_SUCCESS, 4);
|
||||||
|
|
||||||
@ -184,14 +181,13 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write_UINT32(output_stream, length);
|
Stream_Write_UINT32(output_stream, length);
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length) {
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
UINT64 size;
|
UINT64 size;
|
||||||
@ -200,7 +196,7 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device,
|
|||||||
/* Read new size */
|
/* Read new size */
|
||||||
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] size=%" PRIu64,
|
"%s: [file_id=%i] size=%" PRIu64,
|
||||||
__func__, file_id, (uint64_t) size);
|
__func__, file_id, (uint64_t) size);
|
||||||
|
|
||||||
@ -214,14 +210,13 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device,
|
|||||||
completion_id, STATUS_SUCCESS, 4);
|
completion_id, STATUS_SUCCESS, 4);
|
||||||
|
|
||||||
Stream_Write_UINT32(output_stream, length);
|
Stream_Write_UINT32(output_stream, length);
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_set_disposition_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length) {
|
||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
|
|
||||||
@ -234,20 +229,19 @@ void guac_rdpdr_fs_process_set_disposition_info(guac_rdpdr_device* device,
|
|||||||
output_stream = guac_rdpdr_new_io_completion(device,
|
output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_SUCCESS, 4);
|
completion_id, STATUS_SUCCESS, 4);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
Stream_Write_UINT32(output_stream, length);
|
Stream_Write_UINT32(output_stream, length);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length) {
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
UINT64 size;
|
UINT64 size;
|
||||||
@ -256,7 +250,7 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device,
|
|||||||
/* Read new size */
|
/* Read new size */
|
||||||
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] size=%" PRIu64,
|
"%s: [file_id=%i] size=%" PRIu64,
|
||||||
__func__, file_id, (uint64_t) size);
|
__func__, file_id, (uint64_t) size);
|
||||||
|
|
||||||
@ -270,14 +264,13 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device,
|
|||||||
completion_id, STATUS_SUCCESS, 4);
|
completion_id, STATUS_SUCCESS, 4);
|
||||||
|
|
||||||
Stream_Write_UINT32(output_stream, length);
|
Stream_Write_UINT32(output_stream, length);
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_set_basic_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length) {
|
||||||
|
|
||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_SUCCESS, 4);
|
completion_id, STATUS_SUCCESS, 4);
|
||||||
@ -285,13 +278,11 @@ void guac_rdpdr_fs_process_set_basic_info(guac_rdpdr_device* device,
|
|||||||
/* Currently do nothing, just respond */
|
/* Currently do nothing, just respond */
|
||||||
Stream_Write_UINT32(output_stream, length);
|
Stream_Write_UINT32(output_stream, length);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i] IGNORED",
|
"%s: [file_id=%i] IGNORED",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -18,8 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H
|
#ifndef GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H
|
||||||
#define __GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H
|
#define GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handlers for file queries received over the RDPDR channel via the
|
* Handlers for file queries received over the RDPDR channel via the
|
||||||
@ -29,8 +29,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "common-svc.h"
|
||||||
#include "rdpdr_service.h"
|
#include "rdpdr.h"
|
||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
@ -39,59 +39,67 @@
|
|||||||
* "used to query a file for the times of creation, last access, last write,
|
* "used to query a file for the times of creation, last access, last write,
|
||||||
* and change, in addition to file attribute information."
|
* and change, in addition to file attribute information."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query for FileStandardInformation. From the documentation, this
|
* Processes a query for FileStandardInformation. From the documentation, this
|
||||||
* is "used to query for file information such as allocation size, end-of-file
|
* is "used to query for file information such as allocation size, end-of-file
|
||||||
* position, and number of links."
|
* position, and number of links."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query for FileAttributeTagInformation. From the documentation
|
* Processes a query for FileAttributeTagInformation. From the documentation
|
||||||
* this is "used to query for file attribute and reparse tag information."
|
* this is "used to query for file attribute and reparse tag information."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a set operation for FileRenameInformation. From the documentation,
|
* Process a set operation for FileRenameInformation. From the documentation,
|
||||||
* this operation is used to rename a file.
|
* this operation is used to rename a file.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a set operation for FileAllocationInformation. From the
|
* Process a set operation for FileAllocationInformation. From the
|
||||||
* documentation, this operation is used to set a file's allocation size.
|
* documentation, this operation is used to set a file's allocation size.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a set operation for FileDispositionInformation. From the
|
* Process a set operation for FileDispositionInformation. From the
|
||||||
* documentation, this operation is used to mark a file for deletion.
|
* documentation, this operation is used to mark a file for deletion.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_set_disposition_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a set operation for FileEndOfFileInformation. From the
|
* Process a set operation for FileEndOfFileInformation. From the
|
||||||
* documentation, this operation is used "to set end-of-file information for
|
* documentation, this operation is used "to set end-of-file information for
|
||||||
* a file."
|
* a file."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a set operation for FileBasicInformation. From the documentation,
|
* Process a set operation for FileBasicInformation. From the documentation,
|
||||||
* this is "used to set file information such as the times of creation, last
|
* this is "used to set file information such as the times of creation, last
|
||||||
* access, last write, and change, in addition to file attributes."
|
* access, last write, and change, in addition to file attributes."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_set_basic_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int length);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int length);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -18,9 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_messages.h"
|
#include "rdpdr_messages.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
#include "rdp_fs.h"
|
#include "rdp_fs.h"
|
||||||
#include "rdp_status.h"
|
#include "rdp_status.h"
|
||||||
|
|
||||||
@ -28,13 +27,14 @@
|
|||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
#include <winpr/wtypes.h>
|
#include <winpr/wtypes.h>
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_volume_info(guac_rdpdr_device* device,
|
void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_SUCCESS, 21 + GUAC_FILESYSTEM_LABEL_LENGTH);
|
completion_id, STATUS_SUCCESS, 21 + GUAC_FILESYSTEM_LABEL_LENGTH);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -46,14 +46,13 @@ void guac_rdpdr_fs_process_query_volume_info(guac_rdpdr_device* device,
|
|||||||
/* Reserved field must not be sent */
|
/* Reserved field must not be sent */
|
||||||
Stream_Write(output_stream, GUAC_FILESYSTEM_LABEL, GUAC_FILESYSTEM_LABEL_LENGTH);
|
Stream_Write(output_stream, GUAC_FILESYSTEM_LABEL, GUAC_FILESYSTEM_LABEL_LENGTH);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
guac_rdp_fs_info info = {0};
|
guac_rdp_fs_info info = {0};
|
||||||
guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info);
|
guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info);
|
||||||
@ -61,7 +60,7 @@ void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* i
|
|||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_SUCCESS, 28);
|
completion_id, STATUS_SUCCESS, 28);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -71,19 +70,18 @@ void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* i
|
|||||||
Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */
|
Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */
|
||||||
Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */
|
Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_device_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_SUCCESS, 12);
|
completion_id, STATUS_SUCCESS, 12);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -91,21 +89,20 @@ void guac_rdpdr_fs_process_query_device_info(guac_rdpdr_device* device, wStream*
|
|||||||
Stream_Write_UINT32(output_stream, FILE_DEVICE_DISK); /* DeviceType */
|
Stream_Write_UINT32(output_stream, FILE_DEVICE_DISK); /* DeviceType */
|
||||||
Stream_Write_UINT32(output_stream, 0); /* Characteristics */
|
Stream_Write_UINT32(output_stream, 0); /* Characteristics */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_attribute_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
int name_len = guac_utf8_strlen(device->device_name);
|
int name_len = guac_utf8_strlen(device->device_name);
|
||||||
|
|
||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_SUCCESS, 16 + name_len);
|
completion_id, STATUS_SUCCESS, 16 + name_len);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -118,14 +115,13 @@ void guac_rdpdr_fs_process_query_attribute_info(guac_rdpdr_device* device, wStre
|
|||||||
Stream_Write_UINT32(output_stream, name_len);
|
Stream_Write_UINT32(output_stream, name_len);
|
||||||
Stream_Write(output_stream, device->device_name, name_len);
|
Stream_Write(output_stream, device->device_name, name_len);
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id) {
|
||||||
|
|
||||||
guac_rdp_fs_info info = {0};
|
guac_rdp_fs_info info = {0};
|
||||||
guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info);
|
guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info);
|
||||||
@ -133,7 +129,7 @@ void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStre
|
|||||||
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
wStream* output_stream = guac_rdpdr_new_io_completion(device,
|
||||||
completion_id, STATUS_SUCCESS, 36);
|
completion_id, STATUS_SUCCESS, 36);
|
||||||
|
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
|
guac_client_log(svc->client, GUAC_LOG_DEBUG,
|
||||||
"%s: [file_id=%i]",
|
"%s: [file_id=%i]",
|
||||||
__func__, file_id);
|
__func__, file_id);
|
||||||
|
|
||||||
@ -144,9 +140,7 @@ void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStre
|
|||||||
Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */
|
Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */
|
||||||
Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */
|
Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -18,8 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H
|
#ifndef GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H
|
||||||
#define __GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H
|
#define GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handlers for directory queries received over the RDPDR channel via the
|
* Handlers for directory queries received over the RDPDR channel via the
|
||||||
@ -30,8 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
@ -40,32 +39,37 @@
|
|||||||
* documentation, this is "used to query information for a volume on which a
|
* documentation, this is "used to query information for a volume on which a
|
||||||
* file system is mounted."
|
* file system is mounted."
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_volume_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query request for FileFsSizeInformation.
|
* Processes a query request for FileFsSizeInformation.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query request for FileFsAttributeInformation.
|
* Processes a query request for FileFsAttributeInformation.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_attribute_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query request for FileFsFullSizeInformation.
|
* Processes a query request for FileFsFullSizeInformation.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a query request for FileFsDeviceInformation.
|
* Processes a query request for FileFsDeviceInformation.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_fs_process_query_device_info(guac_rdpdr_device* device, wStream* input_stream,
|
void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc,
|
||||||
int file_id, int completion_id);
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -19,11 +19,10 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "rdp.h"
|
#include "rdp.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_fs_messages.h"
|
#include "rdpdr_fs_messages.h"
|
||||||
#include "rdpdr_messages.h"
|
#include "rdpdr_messages.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
|
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/protocol.h>
|
#include <guacamole/protocol.h>
|
||||||
@ -31,99 +30,114 @@
|
|||||||
#include <guacamole/unicode.h>
|
#include <guacamole/unicode.h>
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
static void guac_rdpdr_device_fs_iorequest_handler(guac_rdpdr_device* device,
|
static void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int major_func, int minor_func) {
|
||||||
|
|
||||||
switch (major_func) {
|
switch (major_func) {
|
||||||
|
|
||||||
/* File open */
|
/* File open */
|
||||||
case IRP_MJ_CREATE:
|
case IRP_MJ_CREATE:
|
||||||
guac_rdpdr_fs_process_create(device, input_stream, completion_id);
|
guac_rdpdr_fs_process_create(svc, device, input_stream,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* File close */
|
/* File close */
|
||||||
case IRP_MJ_CLOSE:
|
case IRP_MJ_CLOSE:
|
||||||
guac_rdpdr_fs_process_close(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_close(svc, device, input_stream, file_id,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* File read */
|
/* File read */
|
||||||
case IRP_MJ_READ:
|
case IRP_MJ_READ:
|
||||||
guac_rdpdr_fs_process_read(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_read(svc, device, input_stream, file_id,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* File write */
|
/* File write */
|
||||||
case IRP_MJ_WRITE:
|
case IRP_MJ_WRITE:
|
||||||
guac_rdpdr_fs_process_write(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_write(svc, device, input_stream, file_id,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Device control request (Windows FSCTL_ control codes) */
|
/* Device control request (Windows FSCTL_ control codes) */
|
||||||
case IRP_MJ_DEVICE_CONTROL:
|
case IRP_MJ_DEVICE_CONTROL:
|
||||||
guac_rdpdr_fs_process_device_control(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_device_control(svc, device, input_stream,
|
||||||
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Query volume (drive) information */
|
/* Query volume (drive) information */
|
||||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
||||||
guac_rdpdr_fs_process_volume_info(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_volume_info(svc, device, input_stream,
|
||||||
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Set volume (drive) information */
|
/* Set volume (drive) information */
|
||||||
case IRP_MJ_SET_VOLUME_INFORMATION:
|
case IRP_MJ_SET_VOLUME_INFORMATION:
|
||||||
guac_rdpdr_fs_process_set_volume_info(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_set_volume_info(svc, device, input_stream,
|
||||||
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Query file information */
|
/* Query file information */
|
||||||
case IRP_MJ_QUERY_INFORMATION:
|
case IRP_MJ_QUERY_INFORMATION:
|
||||||
guac_rdpdr_fs_process_file_info(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_file_info(svc, device, input_stream, file_id,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Set file information */
|
/* Set file information */
|
||||||
case IRP_MJ_SET_INFORMATION:
|
case IRP_MJ_SET_INFORMATION:
|
||||||
guac_rdpdr_fs_process_set_file_info(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_set_file_info(svc, device, input_stream,
|
||||||
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MJ_DIRECTORY_CONTROL:
|
case IRP_MJ_DIRECTORY_CONTROL:
|
||||||
|
|
||||||
/* Enumerate directory contents */
|
/* Enumerate directory contents */
|
||||||
if (minor_func == IRP_MN_QUERY_DIRECTORY)
|
if (minor_func == IRP_MN_QUERY_DIRECTORY)
|
||||||
guac_rdpdr_fs_process_query_directory(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_query_directory(svc, device,
|
||||||
|
input_stream, file_id, completion_id);
|
||||||
|
|
||||||
/* Request notification of changes to directory */
|
/* Request notification of changes to directory */
|
||||||
else if (minor_func == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
|
else if (minor_func == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
|
||||||
guac_rdpdr_fs_process_notify_change_directory(device, input_stream,
|
guac_rdpdr_fs_process_notify_change_directory(svc, device,
|
||||||
|
input_stream,
|
||||||
file_id, completion_id);
|
file_id, completion_id);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Lock/unlock portions of a file */
|
/* Lock/unlock portions of a file */
|
||||||
case IRP_MJ_LOCK_CONTROL:
|
case IRP_MJ_LOCK_CONTROL:
|
||||||
guac_rdpdr_fs_process_lock_control(device, input_stream, file_id, completion_id);
|
guac_rdpdr_fs_process_lock_control(svc, device, input_stream,
|
||||||
|
file_id, completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_ERROR,
|
guac_client_log(svc->client, GUAC_LOG_ERROR,
|
||||||
"Unknown filesystem I/O request function: 0x%x/0x%x",
|
"Unknown filesystem I/O request function: 0x%x/0x%x",
|
||||||
major_func, minor_func);
|
major_func, minor_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void guac_rdpdr_device_fs_free_handler(guac_rdpdr_device* device) {
|
static void guac_rdpdr_device_fs_free_handler(guac_rdp_common_svc* svc,
|
||||||
|
guac_rdpdr_device* device) {
|
||||||
|
|
||||||
Stream_Free(device->device_announce, 1);
|
Stream_Free(device->device_announce, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_register_fs(guac_rdpdr* rdpdr, char* drive_name) {
|
void guac_rdpdr_register_fs(guac_rdp_common_svc* svc, char* drive_name) {
|
||||||
|
|
||||||
guac_client* client = rdpdr->client;
|
guac_client* client = svc->client;
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
||||||
int id = rdpdr->devices_registered++;
|
int id = rdpdr->devices_registered++;
|
||||||
|
|
||||||
/* Get new device */
|
/* Get new device */
|
||||||
guac_rdpdr_device* device = &(rdpdr->devices[id]);
|
guac_rdpdr_device* device = &(rdpdr->devices[id]);
|
||||||
|
|
||||||
/* Init device */
|
/* Init device */
|
||||||
device->rdpdr = rdpdr;
|
|
||||||
device->device_id = id;
|
device->device_id = id;
|
||||||
device->device_name = drive_name;
|
device->device_name = drive_name;
|
||||||
int device_name_len = guac_utf8_strlen(device->device_name);
|
int device_name_len = guac_utf8_strlen(device->device_name);
|
@ -18,8 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GUAC_RDPDR_FS_H
|
#ifndef GUAC_RDPDR_FS_H
|
||||||
#define __GUAC_RDPDR_FS_H
|
#define GUAC_RDPDR_FS_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions and macros specific to filesystem handling and initialization
|
* Functions and macros specific to filesystem handling and initialization
|
||||||
@ -33,8 +33,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
|
|
||||||
#include <guacamole/pool.h>
|
#include <guacamole/pool.h>
|
||||||
|
|
||||||
@ -48,7 +47,7 @@
|
|||||||
* @param drive_name
|
* @param drive_name
|
||||||
* The name of the redirected drive to display in the RDP connection.
|
* The name of the redirected drive to display in the RDP connection.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_register_fs(guac_rdpdr* rdpdr, char* drive_name);
|
void guac_rdpdr_register_fs(guac_rdp_common_svc* svc, char* drive_name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -18,10 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "rdp.h"
|
#include "rdp.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_messages.h"
|
#include "rdpdr_messages.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
#include "unicode.h"
|
#include "unicode.h"
|
||||||
|
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
@ -31,7 +30,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static void guac_rdpdr_send_client_announce_reply(guac_rdpdr* rdpdr,
|
static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc,
|
||||||
unsigned int major, unsigned int minor, unsigned int client_id) {
|
unsigned int major, unsigned int minor, unsigned int client_id) {
|
||||||
|
|
||||||
wStream* output_stream = Stream_New(NULL, 12);
|
wStream* output_stream = Stream_New(NULL, 12);
|
||||||
@ -45,13 +44,12 @@ static void guac_rdpdr_send_client_announce_reply(guac_rdpdr* rdpdr,
|
|||||||
Stream_Write_UINT16(output_stream, minor);
|
Stream_Write_UINT16(output_stream, minor);
|
||||||
Stream_Write_UINT32(output_stream, client_id);
|
Stream_Write_UINT32(output_stream, client_id);
|
||||||
|
|
||||||
rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void guac_rdpdr_send_client_name_request(guac_rdpdr* rdpdr, const char* name) {
|
static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc,
|
||||||
|
const char* name) {
|
||||||
|
|
||||||
int name_bytes = strlen(name) + 1;
|
int name_bytes = strlen(name) + 1;
|
||||||
wStream* output_stream = Stream_New(NULL, 16 + name_bytes);
|
wStream* output_stream = Stream_New(NULL, 16 + name_bytes);
|
||||||
@ -66,16 +64,14 @@ static void guac_rdpdr_send_client_name_request(guac_rdpdr* rdpdr, const char* n
|
|||||||
Stream_Write_UINT32(output_stream, name_bytes);
|
Stream_Write_UINT32(output_stream, name_bytes);
|
||||||
Stream_Write(output_stream, name, name_bytes);
|
Stream_Write(output_stream, name, name_bytes);
|
||||||
|
|
||||||
rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void guac_rdpdr_send_client_capability(guac_rdpdr* rdpdr) {
|
static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) {
|
||||||
|
|
||||||
wStream* output_stream = Stream_New(NULL, 256);
|
wStream* output_stream = Stream_New(NULL, 256);
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Sending capabilities...");
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Sending capabilities...");
|
||||||
|
|
||||||
/* Write header */
|
/* Write header */
|
||||||
Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
|
Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
|
||||||
@ -115,14 +111,14 @@ static void guac_rdpdr_send_client_capability(guac_rdpdr* rdpdr) {
|
|||||||
Stream_Write_UINT16(output_stream, 8);
|
Stream_Write_UINT16(output_stream, 8);
|
||||||
Stream_Write_UINT32(output_stream, DRIVE_CAPABILITY_VERSION_02);
|
Stream_Write_UINT32(output_stream, DRIVE_CAPABILITY_VERSION_02);
|
||||||
|
|
||||||
rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
rdpdr->open_handle, Stream_Buffer(output_stream),
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Capabilities sent.");
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Capabilities sent.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdr* rdpdr) {
|
static void guac_rdpdr_send_client_device_list_announce_request(guac_rdp_common_svc* svc) {
|
||||||
|
|
||||||
|
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
||||||
|
|
||||||
/* Calculate number of bytes needed for the stream */
|
/* Calculate number of bytes needed for the stream */
|
||||||
int streamBytes = 16;
|
int streamBytes = 16;
|
||||||
@ -144,19 +140,17 @@ static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdr* rdpd
|
|||||||
Stream_Buffer(rdpdr->devices[i].device_announce),
|
Stream_Buffer(rdpdr->devices[i].device_announce),
|
||||||
rdpdr->devices[i].device_announce_len);
|
rdpdr->devices[i].device_announce_len);
|
||||||
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Registered device %i (%s)",
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Registered device %i (%s)",
|
||||||
rdpdr->devices[i].device_id, rdpdr->devices[i].device_name);
|
rdpdr->devices[i].device_id, rdpdr->devices[i].device_name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
rdpdr->open_handle, Stream_Buffer(output_stream),
|
guac_client_log(svc->client, GUAC_LOG_INFO, "All supported devices sent.");
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "All supported devices sent.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_server_announce(guac_rdpdr* rdpdr,
|
void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream) {
|
wStream* input_stream) {
|
||||||
|
|
||||||
unsigned int major, minor, client_id;
|
unsigned int major, minor, client_id;
|
||||||
@ -169,21 +163,25 @@ void guac_rdpdr_process_server_announce(guac_rdpdr* rdpdr,
|
|||||||
if (minor < 12)
|
if (minor < 12)
|
||||||
client_id = random() & 0xFFFF;
|
client_id = random() & 0xFFFF;
|
||||||
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Connected to RDPDR %u.%u as client 0x%04x", major, minor, client_id);
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Connected to RDPDR %u.%u as client 0x%04x", major, minor, client_id);
|
||||||
|
|
||||||
/* Respond to announce */
|
/* Respond to announce */
|
||||||
guac_rdpdr_send_client_announce_reply(rdpdr, major, minor, client_id);
|
guac_rdpdr_send_client_announce_reply(svc, major, minor, client_id);
|
||||||
|
|
||||||
/* Name request */
|
/* Name request */
|
||||||
guac_rdpdr_send_client_name_request(rdpdr, ((guac_rdp_client *)rdpdr->client->data)->settings->client_name);
|
guac_rdpdr_send_client_name_request(svc, ((guac_rdp_client*) svc->client->data)->settings->client_name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_clientid_confirm(guac_rdpdr* rdpdr, wStream* input_stream) {
|
void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc,
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Client ID confirmed");
|
wStream* input_stream) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Client ID confirmed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream) {
|
void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc,
|
||||||
|
wStream* input_stream) {
|
||||||
|
|
||||||
|
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
||||||
|
|
||||||
unsigned int device_id, ntstatus;
|
unsigned int device_id, ntstatus;
|
||||||
int severity, c, n, facility, code;
|
int severity, c, n, facility, code;
|
||||||
@ -201,11 +199,11 @@ void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream) {
|
|||||||
if (device_id < rdpdr->devices_registered) {
|
if (device_id < rdpdr->devices_registered) {
|
||||||
|
|
||||||
if (severity == 0x0)
|
if (severity == 0x0)
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Device %i (%s) connected successfully",
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Device %i (%s) connected successfully",
|
||||||
device_id, rdpdr->devices[device_id].device_name);
|
device_id, rdpdr->devices[device_id].device_name);
|
||||||
|
|
||||||
else
|
else
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_ERROR, "Problem connecting device %i (%s): "
|
guac_client_log(svc->client, GUAC_LOG_ERROR, "Problem connecting device %i (%s): "
|
||||||
"severity=0x%x, c=0x%x, n=0x%x, facility=0x%x, code=0x%x",
|
"severity=0x%x, c=0x%x, n=0x%x, facility=0x%x, code=0x%x",
|
||||||
device_id, rdpdr->devices[device_id].device_name,
|
device_id, rdpdr->devices[device_id].device_name,
|
||||||
severity, c, n, facility, code);
|
severity, c, n, facility, code);
|
||||||
@ -213,11 +211,14 @@ void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id);
|
guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_device_iorequest(guac_rdpdr* rdpdr, wStream* input_stream) {
|
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;
|
int device_id, file_id, completion_id, major_func, minor_func;
|
||||||
|
|
||||||
@ -233,17 +234,18 @@ void guac_rdpdr_process_device_iorequest(guac_rdpdr* rdpdr, wStream* input_strea
|
|||||||
|
|
||||||
/* Call handler on device */
|
/* Call handler on device */
|
||||||
guac_rdpdr_device* device = &(rdpdr->devices[device_id]);
|
guac_rdpdr_device* device = &(rdpdr->devices[device_id]);
|
||||||
device->iorequest_handler(device, input_stream,
|
device->iorequest_handler(svc, device, input_stream,
|
||||||
file_id, completion_id, major_func, minor_func);
|
file_id, completion_id, major_func, minor_func);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id);
|
guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_server_capability(guac_rdpdr* rdpdr, wStream* input_stream) {
|
void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc,
|
||||||
|
wStream* input_stream) {
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
int i;
|
int i;
|
||||||
@ -262,27 +264,30 @@ void guac_rdpdr_process_server_capability(guac_rdpdr* rdpdr, wStream* input_stre
|
|||||||
Stream_Read_UINT16(input_stream, length);
|
Stream_Read_UINT16(input_stream, length);
|
||||||
|
|
||||||
/* Ignore all for now */
|
/* Ignore all for now */
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring server capability set type=0x%04x, length=%i", type, length);
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Ignoring server capability set type=0x%04x, length=%i", type, length);
|
||||||
Stream_Seek(input_stream, length - 4);
|
Stream_Seek(input_stream, length - 4);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send own capabilities */
|
/* Send own capabilities */
|
||||||
guac_rdpdr_send_client_capability(rdpdr);
|
guac_rdpdr_send_client_capability(svc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_user_loggedon(guac_rdpdr* rdpdr, wStream* input_stream) {
|
void guac_rdpdr_process_user_loggedon(guac_rdp_common_svc* svc,
|
||||||
|
wStream* input_stream) {
|
||||||
|
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "User logged on");
|
guac_client_log(svc->client, GUAC_LOG_INFO, "User logged on");
|
||||||
guac_rdpdr_send_client_device_list_announce_request(rdpdr);
|
guac_rdpdr_send_client_device_list_announce_request(svc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_prn_cache_data(guac_rdpdr* rdpdr, wStream* input_stream) {
|
void guac_rdpdr_process_prn_cache_data(guac_rdp_common_svc* svc,
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring printer cached configuration data");
|
wStream* input_stream) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Ignoring printer cached configuration data");
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_prn_using_xps(guac_rdpdr* rdpdr, wStream* input_stream) {
|
void guac_rdpdr_process_prn_using_xps(guac_rdp_common_svc* svc,
|
||||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Printer unexpectedly switched to XPS mode");
|
wStream* input_stream) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_INFO, "Printer unexpectedly switched to XPS mode");
|
||||||
}
|
}
|
@ -18,12 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GUAC_RDPDR_MESSAGES_H
|
#ifndef GUAC_RDPDR_MESSAGES_H
|
||||||
#define __GUAC_RDPDR_MESSAGES_H
|
#define GUAC_RDPDR_MESSAGES_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
@ -204,14 +203,14 @@
|
|||||||
* Message handlers.
|
* Message handlers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void guac_rdpdr_process_server_announce(guac_rdpdr* rdpdr, wStream* input_stream);
|
void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||||
void guac_rdpdr_process_clientid_confirm(guac_rdpdr* rdpdr, wStream* input_stream);
|
void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||||
void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream);
|
void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||||
void guac_rdpdr_process_device_iorequest(guac_rdpdr* rdpdr, wStream* input_stream);
|
void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||||
void guac_rdpdr_process_server_capability(guac_rdpdr* rdpdr, wStream* input_stream);
|
void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||||
void guac_rdpdr_process_user_loggedon(guac_rdpdr* rdpdr, 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_rdpdr* rdpdr, 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_rdpdr* rdpdr, wStream* input_stream);
|
void guac_rdpdr_process_prn_using_xps(guac_rdp_common_svc* svc, wStream* input_stream);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -18,10 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_messages.h"
|
#include "rdpdr_messages.h"
|
||||||
#include "rdpdr_printer.h"
|
#include "rdpdr_printer.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
#include "rdp.h"
|
#include "rdp.h"
|
||||||
#include "rdp_print_job.h"
|
#include "rdp_print_job.h"
|
||||||
#include "rdp_status.h"
|
#include "rdp_status.h"
|
||||||
@ -42,10 +41,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void guac_rdpdr_process_print_job_create(guac_rdpdr_device* device,
|
void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int completion_id) {
|
||||||
|
|
||||||
guac_client* client = device->rdpdr->client;
|
guac_client* client = svc->client;
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
/* Log creation of print job */
|
/* Log creation of print job */
|
||||||
@ -60,16 +59,14 @@ void guac_rdpdr_process_print_job_create(guac_rdpdr_device* device,
|
|||||||
completion_id, STATUS_SUCCESS, 4);
|
completion_id, STATUS_SUCCESS, 4);
|
||||||
|
|
||||||
Stream_Write_UINT32(output_stream, 0); /* fileId */
|
Stream_Write_UINT32(output_stream, 0); /* fileId */
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device,
|
void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int completion_id) {
|
||||||
|
|
||||||
guac_client* client = device->rdpdr->client;
|
guac_client* client = svc->client;
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
guac_rdp_print_job* job = (guac_rdp_print_job*) rdp_client->active_job;
|
guac_rdp_print_job* job = (guac_rdp_print_job*) rdp_client->active_job;
|
||||||
|
|
||||||
@ -101,16 +98,14 @@ void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device,
|
|||||||
Stream_Write_UINT32(output_stream, length);
|
Stream_Write_UINT32(output_stream, length);
|
||||||
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
Stream_Write_UINT8(output_stream, 0); /* Padding */
|
||||||
|
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device,
|
void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int completion_id) {
|
guac_rdpdr_device* device, wStream* input_stream, int completion_id) {
|
||||||
|
|
||||||
guac_client* client = device->rdpdr->client;
|
guac_client* client = svc->client;
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
guac_rdp_print_job* job = (guac_rdp_print_job*) rdp_client->active_job;
|
guac_rdp_print_job* job = (guac_rdp_print_job*) rdp_client->active_job;
|
||||||
|
|
||||||
@ -124,38 +119,40 @@ void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device,
|
|||||||
completion_id, STATUS_SUCCESS, 4);
|
completion_id, STATUS_SUCCESS, 4);
|
||||||
|
|
||||||
Stream_Write_UINT32(output_stream, 0); /* Padding */
|
Stream_Write_UINT32(output_stream, 0); /* Padding */
|
||||||
device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle,
|
guac_rdp_common_svc_write(svc, output_stream);
|
||||||
device->rdpdr->open_handle, Stream_Buffer(output_stream),
|
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
|
||||||
|
|
||||||
/* Log end of print job */
|
/* Log end of print job */
|
||||||
guac_client_log(client, GUAC_LOG_INFO, "Print job closed");
|
guac_client_log(client, GUAC_LOG_INFO, "Print job closed");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void guac_rdpdr_device_printer_iorequest_handler(guac_rdpdr_device* device,
|
static void guac_rdpdr_device_printer_iorequest_handler(guac_rdp_common_svc* svc,
|
||||||
wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func) {
|
guac_rdpdr_device* device, wStream* input_stream, int file_id,
|
||||||
|
int completion_id, int major_func, int minor_func) {
|
||||||
|
|
||||||
switch (major_func) {
|
switch (major_func) {
|
||||||
|
|
||||||
/* Print job create */
|
/* Print job create */
|
||||||
case IRP_MJ_CREATE:
|
case IRP_MJ_CREATE:
|
||||||
guac_rdpdr_process_print_job_create(device, input_stream, completion_id);
|
guac_rdpdr_process_print_job_create(svc, device, input_stream,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Printer job write */
|
/* Printer job write */
|
||||||
case IRP_MJ_WRITE:
|
case IRP_MJ_WRITE:
|
||||||
guac_rdpdr_process_print_job_write(device, input_stream, completion_id);
|
guac_rdpdr_process_print_job_write(svc, device, input_stream,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Printer job close */
|
/* Printer job close */
|
||||||
case IRP_MJ_CLOSE:
|
case IRP_MJ_CLOSE:
|
||||||
guac_rdpdr_process_print_job_close(device, input_stream, completion_id);
|
guac_rdpdr_process_print_job_close(svc, device, input_stream,
|
||||||
|
completion_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Log unknown */
|
/* Log unknown */
|
||||||
default:
|
default:
|
||||||
guac_client_log(device->rdpdr->client, GUAC_LOG_ERROR,
|
guac_client_log(svc->client, GUAC_LOG_ERROR,
|
||||||
"Unknown printer I/O request function: 0x%x/0x%x",
|
"Unknown printer I/O request function: 0x%x/0x%x",
|
||||||
major_func, minor_func);
|
major_func, minor_func);
|
||||||
|
|
||||||
@ -163,21 +160,22 @@ static void guac_rdpdr_device_printer_iorequest_handler(guac_rdpdr_device* devic
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void guac_rdpdr_device_printer_free_handler(guac_rdpdr_device* device) {
|
static void guac_rdpdr_device_printer_free_handler(guac_rdp_common_svc* svc,
|
||||||
|
guac_rdpdr_device* device) {
|
||||||
|
|
||||||
Stream_Free(device->device_announce, 1);
|
Stream_Free(device->device_announce, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdpdr_register_printer(guac_rdpdr* rdpdr, char* printer_name) {
|
void guac_rdpdr_register_printer(guac_rdp_common_svc* svc, char* printer_name) {
|
||||||
|
|
||||||
|
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
||||||
int id = rdpdr->devices_registered++;
|
int id = rdpdr->devices_registered++;
|
||||||
|
|
||||||
/* Get new device */
|
/* Get new device */
|
||||||
guac_rdpdr_device* device = &(rdpdr->devices[id]);
|
guac_rdpdr_device* device = &(rdpdr->devices[id]);
|
||||||
|
|
||||||
/* Init device */
|
/* Init device */
|
||||||
device->rdpdr = rdpdr;
|
|
||||||
device->device_id = id;
|
device->device_id = id;
|
||||||
device->device_name = printer_name;
|
device->device_name = printer_name;
|
||||||
int device_name_len = guac_utf8_strlen(device->device_name);
|
int device_name_len = guac_utf8_strlen(device->device_name);
|
@ -18,12 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GUAC_RDPDR_PRINTER_H
|
#ifndef GUAC_RDPDR_PRINTER_H
|
||||||
#define __GUAC_RDPDR_PRINTER_H
|
#define GUAC_RDPDR_PRINTER_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "rdpdr.h"
|
||||||
#include "rdpdr_service.h"
|
|
||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
@ -38,7 +37,7 @@
|
|||||||
* The name of the printer that will be registered with the RDP
|
* The name of the printer that will be registered with the RDP
|
||||||
* connection and passed through to the server.
|
* connection and passed through to the server.
|
||||||
*/
|
*/
|
||||||
void guac_rdpdr_register_printer(guac_rdpdr* rdpdr, char* printer_name);
|
void guac_rdpdr_register_printer(guac_rdp_common_svc* svc, char* printer_name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user