From 667d78206d58ff14971ddd0648ccda9dac49e25a Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Fri, 5 Aug 2011 15:43:48 +0800 Subject: [PATCH] rdpdr: add capability processing. --- channels/rdpdr/CMakeLists.txt | 3 + channels/rdpdr/rdpdr_capabilities.c | 187 ++++++++++++++++++++++++++++ channels/rdpdr/rdpdr_capabilities.h | 29 +++++ channels/rdpdr/rdpdr_main.c | 18 +-- channels/rdpdr/rdpdr_main.h | 41 ++++++ 5 files changed, 265 insertions(+), 13 deletions(-) create mode 100644 channels/rdpdr/rdpdr_capabilities.c create mode 100644 channels/rdpdr/rdpdr_capabilities.h create mode 100644 channels/rdpdr/rdpdr_main.h diff --git a/channels/rdpdr/CMakeLists.txt b/channels/rdpdr/CMakeLists.txt index dba633bc4..b0019f45b 100644 --- a/channels/rdpdr/CMakeLists.txt +++ b/channels/rdpdr/CMakeLists.txt @@ -20,9 +20,12 @@ set(RDPDR_SRCS rdpdr_constants.h rdpdr_types.h + rdpdr_capabilities.c + rdpdr_capabilities.h devman.c devman.h rdpdr_main.c + rdpdr_main.h ) add_library(rdpdr SHARED ${RDPDR_SRCS}) diff --git a/channels/rdpdr/rdpdr_capabilities.c b/channels/rdpdr/rdpdr_capabilities.c new file mode 100644 index 000000000..c31dbeadf --- /dev/null +++ b/channels/rdpdr/rdpdr_capabilities.c @@ -0,0 +1,187 @@ +/** + * FreeRDP: A Remote Desktop Protocol client. + * File System Virtual Channel + * + * Copyright 2010-2011 Marc-Andre Moreau + * Copyright 2010-2011 Vic Lee + * + * Licensed 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 +#include +#include +#include +#include + +#include "rdpdr_types.h" +#include "rdpdr_constants.h" +#include "rdpdr_capabilities.h" + +/* Output device redirection capability set header */ +static void rdpdr_write_capset_header(STREAM* data_out, uint16 capabilityType, uint16 capabilityLength, uint32 version) +{ + stream_write_uint16(data_out, capabilityType); + stream_write_uint16(data_out, capabilityLength); + stream_write_uint32(data_out, version); +} + +/* Output device direction general capability set */ +static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, STREAM* data_out) +{ + rdpdr_write_capset_header(data_out, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02); + + stream_write_uint32(data_out, 0); /* osType, ignored on receipt */ + stream_write_uint32(data_out, 0); /* osVersion, unused and must be set to zero */ + stream_write_uint16(data_out, 1); /* protocolMajorVersion, must be set to 1 */ + stream_write_uint16(data_out, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */ + stream_write_uint32(data_out, 0x0000FFFF); /* ioCode1 */ + stream_write_uint32(data_out, 0); /* ioCode2, must be set to zero, reserved for future use */ + stream_write_uint32(data_out, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ + stream_write_uint32(data_out, ENABLE_ASYNCIO); /* extraFlags1 */ + stream_write_uint32(data_out, 0); /* extraFlags2, must be set to zero, reserved for future use */ + stream_write_uint32(data_out, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */ +} + +/* Process device direction general capability set */ +static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, STREAM* data_in) +{ + uint16 capabilityLength; + + stream_read_uint16(data_in, capabilityLength); + stream_seek(data_in, capabilityLength - 4); +} + +/* Output printer direction capability set */ +static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, STREAM* data_out) +{ + rdpdr_write_capset_header(data_out, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01); +} + +/* Process printer direction capability set */ +static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, STREAM* data_in) +{ + uint16 capabilityLength; + + stream_read_uint16(data_in, capabilityLength); + stream_seek(data_in, capabilityLength - 4); +} + +/* Output port redirection capability set */ +static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, STREAM* data_out) +{ + rdpdr_write_capset_header(data_out, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01); +} + +/* Process port redirection capability set */ +static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, STREAM* data_in) +{ + uint16 capabilityLength; + + stream_read_uint16(data_in, capabilityLength); + stream_seek(data_in, capabilityLength - 4); +} + +/* Output drive redirection capability set */ +static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, STREAM* data_out) +{ + rdpdr_write_capset_header(data_out, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02); +} + +/* Process drive redirection capability set */ +static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, STREAM* data_in) +{ + uint16 capabilityLength; + + stream_read_uint16(data_in, capabilityLength); + stream_seek(data_in, capabilityLength - 4); +} + +/* Output smart card redirection capability set */ +static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, STREAM* data_out) +{ + rdpdr_write_capset_header(data_out, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01); +} + +/* Process smartcard redirection capability set */ +static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, STREAM* data_in) +{ + uint16 capabilityLength; + + stream_read_uint16(data_in, capabilityLength); + stream_seek(data_in, capabilityLength - 4); +} + +void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, STREAM* data_in) +{ + uint16 i; + uint16 numCapabilities; + uint16 capabilityType; + + stream_read_uint16(data_in, numCapabilities); + stream_seek(data_in, 2); /* pad (2 bytes) */ + + for(i = 0; i < numCapabilities; i++) + { + stream_read_uint16(data_in, capabilityType); + + switch (capabilityType) + { + case CAP_GENERAL_TYPE: + rdpdr_process_general_capset(rdpdr, data_in); + break; + + case CAP_PRINTER_TYPE: + rdpdr_process_printer_capset(rdpdr, data_in); + break; + + case CAP_PORT_TYPE: + rdpdr_process_port_capset(rdpdr, data_in); + break; + + case CAP_DRIVE_TYPE: + rdpdr_process_drive_capset(rdpdr, data_in); + break; + + case CAP_SMARTCARD_TYPE: + rdpdr_process_smartcard_capset(rdpdr, data_in); + break; + + default: + DEBUG_WARN("Unknown capabilityType %d", capabilityType); + break; + } + } +} + +void rdpdr_send_capability_response(rdpdrPlugin* rdpdr) +{ + STREAM* data_out; + + data_out = stream_new(256); + + stream_write_uint16(data_out, RDPDR_CTYP_CORE); + stream_write_uint16(data_out, PAKID_CORE_CLIENT_CAPABILITY); + + stream_write_uint16(data_out, 5); /* numCapabilities */ + stream_write_uint16(data_out, 0); /* pad */ + + rdpdr_write_general_capset(rdpdr, data_out); + rdpdr_write_printer_capset(rdpdr, data_out); + rdpdr_write_port_capset(rdpdr, data_out); + rdpdr_write_drive_capset(rdpdr, data_out); + rdpdr_write_smartcard_capset(rdpdr, data_out); + + svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out); +} diff --git a/channels/rdpdr/rdpdr_capabilities.h b/channels/rdpdr/rdpdr_capabilities.h new file mode 100644 index 000000000..28b83c745 --- /dev/null +++ b/channels/rdpdr/rdpdr_capabilities.h @@ -0,0 +1,29 @@ +/** + * FreeRDP: A Remote Desktop Protocol client. + * File System Virtual Channel + * + * Copyright 2010-2011 Marc-Andre Moreau + * Copyright 2010-2011 Vic Lee + * + * Licensed 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 __RDPDR_CAPABILITIES_H +#define __RDPDR_CAPABILITIES_H + +#include "rdpdr_main.h" + +void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, STREAM* data_in); +void rdpdr_send_capability_response(rdpdrPlugin* rdpdr); + +#endif /* __RDPDR_CAPABILITIES_H */ diff --git a/channels/rdpdr/rdpdr_main.c b/channels/rdpdr/rdpdr_main.c index b6c6bf738..4efa809c3 100644 --- a/channels/rdpdr/rdpdr_main.c +++ b/channels/rdpdr/rdpdr_main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #ifdef HAVE_UNISTD_H @@ -35,19 +36,8 @@ #include "rdpdr_types.h" #include "rdpdr_constants.h" #include "devman.h" - -typedef struct rdpdr_plugin rdpdrPlugin; -struct rdpdr_plugin -{ - rdpSvcPlugin plugin; - - DEVMAN* devman; - - uint16 versionMajor; - uint16 versionMinor; - uint16 clientID; - char computerName[256]; -}; +#include "rdpdr_capabilities.h" +#include "rdpdr_main.h" static void rdpdr_process_connect(rdpSvcPlugin* plugin) { @@ -147,6 +137,8 @@ static void rdpdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) case PAKID_CORE_SERVER_CAPABILITY: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_CAPABILITY"); + rdpdr_process_capability_request(rdpdr, data_in); + rdpdr_send_capability_response(rdpdr); break; case PAKID_CORE_CLIENTID_CONFIRM: diff --git a/channels/rdpdr/rdpdr_main.h b/channels/rdpdr/rdpdr_main.h new file mode 100644 index 000000000..af867fbf5 --- /dev/null +++ b/channels/rdpdr/rdpdr_main.h @@ -0,0 +1,41 @@ +/** + * FreeRDP: A Remote Desktop Protocol client. + * File System Virtual Channel + * + * Copyright 2010-2011 Marc-Andre Moreau + * Copyright 2010-2011 Vic Lee + * + * Licensed 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 __RDPDR_MAIN_H +#define __RDPDR_MAIN_H + +#include + +#include "rdpdr_types.h" + +typedef struct rdpdr_plugin rdpdrPlugin; +struct rdpdr_plugin +{ + rdpSvcPlugin plugin; + + DEVMAN* devman; + + uint16 versionMajor; + uint16 versionMinor; + uint16 clientID; + char computerName[256]; +}; + +#endif /* __RDPDR_MAIN_H */