From 06ef43bd2cdb817fd8b75fe64428de95bc60bcec Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 22 Jun 2013 17:43:05 -0700 Subject: [PATCH] Actually read print job data. --- src/protocols/rdp/Makefile.am | 2 + src/protocols/rdp/guac_rdpdr/rdpdr_messages.c | 54 +++++++++---- src/protocols/rdp/guac_rdpdr/rdpdr_messages.h | 22 +++++- src/protocols/rdp/guac_rdpdr/rdpdr_printer.c | 75 +++++++++++++++++++ src/protocols/rdp/guac_rdpdr/rdpdr_printer.h | 53 +++++++++++++ src/protocols/rdp/guac_rdpdr/rdpdr_service.c | 4 - src/protocols/rdp/guac_rdpdr/rdpdr_service.h | 2 + 7 files changed, 193 insertions(+), 19 deletions(-) create mode 100644 src/protocols/rdp/guac_rdpdr/rdpdr_printer.c create mode 100644 src/protocols/rdp/guac_rdpdr/rdpdr_printer.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index f885a372..e7795779 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -67,10 +67,12 @@ guac_rdpsnd_la_SOURCES = \ guac_rdpdr_la_SOURCES = \ guac_rdpdr/rdpdr_messages.c \ + guac_rdpdr/rdpdr_printer.c \ guac_rdpdr/rdpdr_service.c noinst_HEADERS = \ guac_rdpdr/rdpdr_messages.h \ + guac_rdpdr/rdpdr_printer.h \ guac_rdpdr/rdpdr_service.h \ guac_rdpsnd/rdpsnd_messages.h \ guac_rdpsnd/rdpsnd_service.h \ diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c index 07ae4f9e..5e583e70 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c @@ -48,6 +48,7 @@ #include "rdpdr_service.h" #include "rdpdr_messages.h" +#include "rdpdr_printer.h" #include "client.h" @@ -229,15 +230,46 @@ void guac_rdpdr_process_device_reply(guac_rdpdrPlugin* rdpdr, STREAM* input_stre void guac_rdpdr_process_device_iorequest(guac_rdpdrPlugin* rdpdr, STREAM* input_stream) { - /* STUB */ - guac_client_log_info(rdpdr->client, "STUB: device_iorequest"); + int device_id, completion_id, major_func, minor_func; -} + /* Read header */ + stream_read_uint32(input_stream, device_id); + stream_seek(input_stream, 4); /* file_id - currently skipped (not used in printer) */ + stream_read_uint32(input_stream, completion_id); + stream_read_uint32(input_stream, major_func); + stream_read_uint32(input_stream, minor_func); -void guac_rdpdr_process_device_iocompletion(guac_rdpdrPlugin* rdpdr, STREAM* input_stream) { + /* If printer, run printer handlers */ + if (device_id == GUAC_PRINTER_DEVICE_ID) { - /* STUB */ - guac_client_log_info(rdpdr->client, "STUB: device_iocompletion"); + switch (major_func) { + + /* Print job create */ + case IRP_MJ_CREATE: + guac_rdpdr_process_print_job_create(rdpdr, input_stream, completion_id); + break; + + /* Printer job write */ + case IRP_MJ_WRITE: + guac_rdpdr_process_print_job_write(rdpdr, input_stream, completion_id); + break; + + /* Printer job close */ + case IRP_MJ_CLOSE: + guac_rdpdr_process_print_job_close(rdpdr, input_stream, completion_id); + break; + + /* Log unknown */ + default: + guac_client_log_error(rdpdr->client, "Unknown printer I/O request function: 0x%x/0x%x", + major_func, minor_func); + + } + + } + + else + guac_client_log_error(rdpdr->client, "Unknown device ID: 0x%08x", device_id); } @@ -278,16 +310,10 @@ void guac_rdpdr_process_user_loggedon(guac_rdpdrPlugin* rdpdr, STREAM* input_str } void guac_rdpdr_process_prn_cache_data(guac_rdpdrPlugin* rdpdr, STREAM* input_stream) { - - /* STUB */ - guac_client_log_info(rdpdr->client, "STUB: prn_cache_data"); - + guac_client_log_info(rdpdr->client, "Ignoring printer cached configuration data"); } void guac_rdpdr_process_prn_using_xps(guac_rdpdrPlugin* rdpdr, STREAM* input_stream) { - - /* STUB */ - guac_client_log_info(rdpdr->client, "STUB: prn_using_xps"); - + guac_client_log_info(rdpdr->client, "Printer unexpectedly switched to XPS mode"); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h index 025463c2..12fb83c7 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h @@ -38,6 +38,8 @@ #ifndef __GUAC_RDPDR_MESSAGES_H #define __GUAC_RDPDR_MESSAGES_H +#include "rdpdr_service.h" + /** * Identifies the "core" component of RDPDR as the destination of the received * packet. @@ -158,6 +160,25 @@ #define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 #define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 +/* + * I/O requests. + */ + +#define IRP_MJ_CREATE 0x00000000 +#define IRP_MJ_CLOSE 0x00000002 +#define IRP_MJ_READ 0x00000003 +#define IRP_MJ_WRITE 0x00000004 +#define IRP_MJ_DEVICE_CONTROL 0x0000000E +#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0000000A +#define IRP_MJ_SET_VOLUME_INFORMATION 0x0000000B +#define IRP_MJ_QUERY_INFORMATION 0x00000005 +#define IRP_MJ_SET_INFORMATION 0x00000006 +#define IRP_MJ_DIRECTORY_CONTROL 0x0000000C +#define IRP_MJ_LOCK_CONTROL 0x00000011 + +#define IRP_MN_QUERY_DIRECTORY 0x00000001 +#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002 + /* * Message handlers. */ @@ -166,7 +187,6 @@ void guac_rdpdr_process_server_announce(guac_rdpdrPlugin* rdpdr, STREAM* input_s void guac_rdpdr_process_clientid_confirm(guac_rdpdrPlugin* rdpdr, STREAM* input_stream); void guac_rdpdr_process_device_reply(guac_rdpdrPlugin* rdpdr, STREAM* input_stream); void guac_rdpdr_process_device_iorequest(guac_rdpdrPlugin* rdpdr, STREAM* input_stream); -void guac_rdpdr_process_device_iocompletion(guac_rdpdrPlugin* rdpdr, STREAM* input_stream); void guac_rdpdr_process_server_capability(guac_rdpdrPlugin* rdpdr, STREAM* input_stream); void guac_rdpdr_process_user_loggedon(guac_rdpdrPlugin* rdpdr, STREAM* input_stream); void guac_rdpdr_process_prn_cache_data(guac_rdpdrPlugin* rdpdr, STREAM* input_stream); diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c new file mode 100644 index 00000000..e669f781 --- /dev/null +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c @@ -0,0 +1,75 @@ + +#include +#include + +#include "rdpdr_messages.h" +#include "rdpdr_service.h" + +void guac_rdpdr_process_print_job_create(guac_rdpdrPlugin* rdpdr, STREAM* input_stream, int completion_id) { + + STREAM* output_stream = stream_new(24); + + guac_client_log_info(rdpdr->client, "Print job created"); + + /* 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, GUAC_PRINTER_DEVICE_ID); + stream_write_uint32(output_stream, completion_id); + stream_write_uint32(output_stream, 0); /* NTSTATUS - success */ + stream_write_uint32(output_stream, 0); /* fileId */ + + svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream); + +} + +void guac_rdpdr_process_print_job_write(guac_rdpdrPlugin* rdpdr, STREAM* input_stream, int completion_id) { + + int length; + + STREAM* output_stream = stream_new(24); + + stream_read_uint32(input_stream, length); + stream_seek(input_stream, 8); /* Offset */ + stream_seek(input_stream, 20); /* Padding */ + + /* TODO: Here, read data */ + guac_client_log_info(rdpdr->client, "Data received: %i bytes", length); + + /* 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, GUAC_PRINTER_DEVICE_ID); + stream_write_uint32(output_stream, completion_id); + stream_write_uint32(output_stream, 0); /* NTSTATUS - success */ + stream_write_uint32(output_stream, length); + stream_write_uint8(output_stream, 0); /* padding (stated as optional in spec, but requests fail without) */ + + svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream); + +} + +void guac_rdpdr_process_print_job_close(guac_rdpdrPlugin* rdpdr, STREAM* input_stream, int completion_id) { + + STREAM* output_stream = stream_new(24); + + guac_client_log_info(rdpdr->client, "Print job closed"); + + /* 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, GUAC_PRINTER_DEVICE_ID); + stream_write_uint32(output_stream, completion_id); + stream_write_uint32(output_stream, 0); /* NTSTATUS - success */ + stream_write_uint32(output_stream, 0); /* padding*/ + + svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream); + +} + diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h new file mode 100644 index 00000000..01689d90 --- /dev/null +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h @@ -0,0 +1,53 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-rdp. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __GUAC_RDPDR_PRINTER_H +#define __GUAC_RDPDR_PRINTER_H + +#include +#include + +/* + * Message handlers. + */ + +void guac_rdpdr_process_print_job_create(guac_rdpdrPlugin* rdpdr, STREAM* input_stream, int completion_id); +void guac_rdpdr_process_print_job_write(guac_rdpdrPlugin* rdpdr, STREAM* input_stream, int completion_id); +void guac_rdpdr_process_print_job_close(guac_rdpdrPlugin* rdpdr, STREAM* input_stream, int completion_id); + +#endif + diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c index 7adfd827..c211838c 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c @@ -119,10 +119,6 @@ void guac_rdpdr_process_receive(rdpSvcPlugin* plugin, guac_rdpdr_process_device_iorequest(rdpdr, input_stream); break; - case PAKID_CORE_DEVICE_IOCOMPLETION: - guac_rdpdr_process_device_iocompletion(rdpdr, input_stream); - break; - case PAKID_CORE_SERVER_CAPABILITY: guac_rdpdr_process_server_capability(rdpdr, input_stream); break; diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.h b/src/protocols/rdp/guac_rdpdr/rdpdr_service.h index ebb6e1db..39f78cef 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_service.h @@ -38,6 +38,8 @@ #ifndef __GUAC_RDPDR_SERVICE_H #define __GUAC_RDPDR_SERVICE_H +#include + /** * Structure representing the current state of the Guacamole RDPDR plugin for * FreeRDP.