diff --git a/channels/rdpdr/client/devman.c b/channels/rdpdr/client/devman.c index 2e1666204..315339d92 100644 --- a/channels/rdpdr/client/devman.c +++ b/channels/rdpdr/client/devman.c @@ -6,6 +6,7 @@ * Copyright 2010-2012 Marc-Andre Moreau * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +43,9 @@ void devman_device_free(DEVICE* device) { + if (!device) + return; + IFCALL(device->Free, device); } @@ -49,6 +53,9 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr) { DEVMAN* devman; + if (!rdpdr) + return NULL; + devman = (DEVMAN*) calloc(1, sizeof(DEVMAN)); if (!devman) @@ -84,6 +91,9 @@ void devman_unregister_device(DEVMAN* devman, void* key) { DEVICE* device; + if (!devman || !key) + return; + device = (DEVICE*) ListDictionary_Remove(devman->devices, key); if (device) @@ -99,6 +109,12 @@ static UINT devman_register_device(DEVMAN* devman, DEVICE* device) { void* key = NULL; + if (!devman || !device) + return ERROR_INVALID_PARAMETER; + + if (device->type != RDPDR_DTYP_FILESYSTEM) + return CHANNEL_RC_OK; + device->id = devman->id_sequence++; key = (void*) (size_t) device->id; @@ -115,6 +131,9 @@ DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id) DEVICE* device = NULL; void* key = (void*) (size_t) id; + if (!devman) + return NULL; + device = (DEVICE*) ListDictionary_GetItemValue(devman->devices, key); return device; @@ -137,6 +156,9 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext DEVICE_SERVICE_ENTRY_POINTS ep; PDEVICE_SERVICE_ENTRY entry = NULL; + if (!devman || !device || !rdpcontext) + return ERROR_INVALID_PARAMETER; + if (device->Type == RDPDR_DTYP_FILESYSTEM) ServiceName = DRIVE_SERVICE_NAME; else if (device->Type == RDPDR_DTYP_PRINT) diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index 2d1f96506..d8eaece36 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -77,18 +77,28 @@ static UINT irp_complete(IRP* irp) return error; } -IRP* irp_new(DEVMAN* devman, wStream* s) +IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) { IRP* irp; DEVICE* device; UINT32 DeviceId; + if (Stream_GetRemainingLength(s) < 20) + { + if (error) + *error = ERROR_INVALID_DATA; + return NULL; + } + Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */ device = devman_get_device_by_id(devman, DeviceId); if (!device) { - WLog_ERR(TAG, "devman_get_device_by_id failed!"); + WLog_WARN(TAG, "devman_get_device_by_id failed!"); + if (error) + *error = CHANNEL_RC_OK; + return NULL; }; @@ -97,6 +107,8 @@ IRP* irp_new(DEVMAN* devman, wStream* s) if (!irp) { WLog_ERR(TAG, "_aligned_malloc failed!"); + if (error) + *error = CHANNEL_RC_NO_MEMORY; return NULL; } @@ -117,6 +129,8 @@ IRP* irp_new(DEVMAN* devman, wStream* s) { WLog_ERR(TAG, "Stream_New failed!"); _aligned_free(irp); + if (error) + *error = CHANNEL_RC_NO_MEMORY; return NULL; } Stream_Write_UINT16(irp->output, RDPDR_CTYP_CORE); /* Component (2 bytes) */ @@ -131,5 +145,8 @@ IRP* irp_new(DEVMAN* devman, wStream* s) irp->thread = NULL; irp->cancelled = FALSE; + if (error) + *error = CHANNEL_RC_OK; + return irp; } diff --git a/channels/rdpdr/client/irp.h b/channels/rdpdr/client/irp.h index d94366373..17d75acde 100644 --- a/channels/rdpdr/client/irp.h +++ b/channels/rdpdr/client/irp.h @@ -23,6 +23,6 @@ #include "rdpdr_main.h" -IRP* irp_new(DEVMAN* devman, wStream* s); +IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error); #endif /* FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H */ diff --git a/channels/rdpdr/client/rdpdr_capabilities.c b/channels/rdpdr/client/rdpdr_capabilities.c index 26f6d529e..4ff3ef594 100644 --- a/channels/rdpdr/client/rdpdr_capabilities.c +++ b/channels/rdpdr/client/rdpdr_capabilities.c @@ -4,8 +4,9 @@ * * Copyright 2010-2011 Vic Lee * Copyright 2010-2012 Marc-Andre Moreau - * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015-2016 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,12 +61,21 @@ static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process device direction general capability set */ -static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } /* Output printer direction capability set */ @@ -75,12 +85,21 @@ static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process printer direction capability set */ -static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } /* Output port redirection capability set */ @@ -90,12 +109,21 @@ static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process port redirection capability set */ -static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } /* Output drive redirection capability set */ @@ -105,12 +133,21 @@ static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process drive redirection capability set */ -static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } /* Output smart card redirection capability set */ @@ -120,53 +157,77 @@ static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process smartcard redirection capability set */ -static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } -void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) +UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) { + UINT status = CHANNEL_RC_OK; UINT16 i; UINT16 numCapabilities; UINT16 capabilityType; + if (!rdpdr || !s) + return CHANNEL_RC_NULL_DATA; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, numCapabilities); Stream_Seek(s, 2); /* pad (2 bytes) */ for (i = 0; i < numCapabilities; i++) { + if (Stream_GetRemainingLength(s) < sizeof(UINT16)) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityType); switch (capabilityType) { - case CAP_GENERAL_TYPE: - rdpdr_process_general_capset(rdpdr, s); - break; + case CAP_GENERAL_TYPE: + status = rdpdr_process_general_capset(rdpdr, s); + break; - case CAP_PRINTER_TYPE: - rdpdr_process_printer_capset(rdpdr, s); - break; + case CAP_PRINTER_TYPE: + status = rdpdr_process_printer_capset(rdpdr, s); + break; - case CAP_PORT_TYPE: - rdpdr_process_port_capset(rdpdr, s); - break; + case CAP_PORT_TYPE: + status = rdpdr_process_port_capset(rdpdr, s); + break; - case CAP_DRIVE_TYPE: - rdpdr_process_drive_capset(rdpdr, s); - break; + case CAP_DRIVE_TYPE: + status = rdpdr_process_drive_capset(rdpdr, s); + break; - case CAP_SMARTCARD_TYPE: - rdpdr_process_smartcard_capset(rdpdr, s); - break; + case CAP_SMARTCARD_TYPE: + status = rdpdr_process_smartcard_capset(rdpdr, s); + break; - default: - break; + default: + break; } + + if (status != CHANNEL_RC_OK) + return status; } + + return CHANNEL_RC_OK; } /** diff --git a/channels/rdpdr/client/rdpdr_capabilities.h b/channels/rdpdr/client/rdpdr_capabilities.h index bc2ef8b9e..d4e1ecb27 100644 --- a/channels/rdpdr/client/rdpdr_capabilities.h +++ b/channels/rdpdr/client/rdpdr_capabilities.h @@ -25,7 +25,7 @@ #include "rdpdr_main.h" -void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s); +UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s); UINT rdpdr_send_capability_response(rdpdrPlugin* rdpdr); #endif /* FREERDP_CHANNEL_RDPDR_CLIENT_CAPABILITIES_H */ diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 30bd2681d..87ee6fbdb 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -4,8 +4,9 @@ * * Copyright 2010-2011 Vic Lee * Copyright 2010-2012 Marc-Andre Moreau - * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015-2016 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,7 +82,7 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou UINT32 i; wStream* s; - s = Stream_New(NULL, 256); + s = Stream_New(NULL, count * sizeof(UINT32) + 8); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -429,7 +430,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) BOOL dev_found = FALSE; device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]); - if (!device_ext) + if (!device_ext || !device_ext->path) continue; /* not plugable device */ @@ -496,7 +497,6 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) free(drive->Path); free(drive->Name); free(drive); - error = CHANNEL_RC_NO_MEMORY; goto cleanup; } } @@ -517,15 +517,15 @@ static void* drive_hotplug_thread_func(void* arg) struct timeval tv; int rv; UINT error; - DWORD status; + DWORD status; rdpdr = (rdpdrPlugin*) arg; if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { WLog_ERR(TAG, "CreateEvent failed!"); - error = ERROR_INTERNAL_ERROR; - goto out; + error = ERROR_INTERNAL_ERROR; + goto out; } mfd = open("/proc/mounts", O_RDONLY, 0); @@ -533,8 +533,8 @@ static void* drive_hotplug_thread_func(void* arg) if (mfd < 0) { WLog_ERR(TAG, "ERROR: Unable to open /proc/mounts."); - error = ERROR_INTERNAL_ERROR; - goto out; + error = ERROR_INTERNAL_ERROR; + goto out; } FD_ZERO(&rfds); @@ -545,18 +545,18 @@ static void* drive_hotplug_thread_func(void* arg) if ((error = handle_hotplug(rdpdr))) { WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); - goto out; + goto out; } while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0) { - status = WaitForSingleObject(rdpdr->stopEvent, 0); - if (status == WAIT_FAILED) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); - goto out; - } + status = WaitForSingleObject(rdpdr->stopEvent, 0); + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); + goto out; + } if (status == WAIT_OBJECT_0) break; @@ -566,7 +566,7 @@ static void* drive_hotplug_thread_func(void* arg) if ((error = handle_hotplug(rdpdr))) { WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); - goto out; + goto out; } } @@ -577,11 +577,11 @@ static void* drive_hotplug_thread_func(void* arg) } out: - if (error && rdpdr->rdpcontext) - setChannelError(rdpdr->rdpcontext, error, "drive_hotplug_thread_func reported an error"); + if (error && rdpdr->rdpcontext) + setChannelError(rdpdr->rdpcontext, error, "drive_hotplug_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread((DWORD)error); + return NULL; } /** @@ -591,21 +591,22 @@ out: */ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) { - UINT error; + UINT error; + if (rdpdr->hotplugThread) { if (rdpdr->stopEvent) SetEvent(rdpdr->stopEvent); if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); - return error; - } + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); + return error; + } rdpdr->hotplugThread = NULL; } - return CHANNEL_RC_OK; + return CHANNEL_RC_OK; } #endif @@ -661,13 +662,18 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) return error; } -static void rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* s) { + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, rdpdr->versionMajor); Stream_Read_UINT16(s, rdpdr->versionMinor); Stream_Read_UINT32(s, rdpdr->clientID); rdpdr->sequenceId++; + + return CHANNEL_RC_OK; } /** @@ -683,7 +689,7 @@ static UINT rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr) if (!s) { WLog_ERR(TAG, "Stream_New failed!"); - return CHANNEL_RC_OK; + return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ @@ -733,12 +739,15 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr) return rdpdr_send(rdpdr, s); } -static void rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s) { UINT16 versionMajor; UINT16 versionMinor; UINT32 clientID; + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, versionMajor); Stream_Read_UINT16(s, versionMinor); Stream_Read_UINT32(s, clientID); @@ -750,9 +759,9 @@ static void rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s } if (clientID != rdpdr->clientID) - { rdpdr->clientID = clientID; - } + + return CHANNEL_RC_OK; } /** @@ -804,13 +813,13 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use */ if ((rdpdr->versionMinor == 0x0005) || - (device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn) + (device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn) { data_len = (int) (device->data == NULL ? 0 : Stream_GetPosition(device->data)); if (!Stream_EnsureRemainingCapacity(s, 20 + data_len)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); - return CHANNEL_RC_NO_MEMORY; + return ERROR_INVALID_DATA; } Stream_Write_UINT32(s, device->type); /* deviceType */ @@ -859,20 +868,20 @@ static UINT rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s) IRP* irp; UINT error = CHANNEL_RC_OK; - irp = irp_new(rdpdr->devman, s); + irp = irp_new(rdpdr->devman, s, &error); if (!irp) { - WLog_ERR(TAG, "irp_new failed!"); - return CHANNEL_RC_NO_MEMORY; + WLog_ERR(TAG, "irp_new failed with %lu!", error); + return error; } IFCALLRET(irp->device->IRPRequest, error, irp->device, irp); - if (error) - WLog_ERR(TAG, "device->IRPRequest failed with error %lu", error); + if (error) + WLog_ERR(TAG, "device->IRPRequest failed with error %lu", error); - return error; + return error; } /** @@ -921,6 +930,12 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) UINT32 status; UINT error; + if (!rdpdr || !s) + return CHANNEL_RC_NULL_DATA; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, component); /* Component (2 bytes) */ Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */ @@ -928,70 +943,77 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) { switch (packetId) { - case PAKID_CORE_SERVER_ANNOUNCE: - rdpdr_process_server_announce_request(rdpdr, s); - if ((error = rdpdr_send_client_announce_reply(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %lu", error); - return error; - } - if ((error = rdpdr_send_client_name_request(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %lu", error); - return error; - } - if ((error = rdpdr_process_init(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_process_init failed with error %lu", error); - return error; - } - break; + case PAKID_CORE_SERVER_ANNOUNCE: + if ((error = rdpdr_process_server_announce_request(rdpdr, s))) + return error; + if ((error = rdpdr_send_client_announce_reply(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %lu", error); + return error; + } + if ((error = rdpdr_send_client_name_request(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %lu", error); + return error; + } + if ((error = rdpdr_process_init(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_process_init failed with error %lu", error); + return error; + } + break; - case PAKID_CORE_SERVER_CAPABILITY: - rdpdr_process_capability_request(rdpdr, s); - if ((error = rdpdr_send_capability_response(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %lu", error); - return error; - } - break; + case PAKID_CORE_SERVER_CAPABILITY: + if ((error = rdpdr_process_capability_request(rdpdr, s))) + return error; + if ((error = rdpdr_send_capability_response(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %lu", error); + return error; + } + break; - case PAKID_CORE_CLIENTID_CONFIRM: - rdpdr_process_server_clientid_confirm(rdpdr, s); - if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) - { - WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu", error); - return error; - } - break; + case PAKID_CORE_CLIENTID_CONFIRM: + if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s))) + return error; - case PAKID_CORE_USER_LOGGEDON: - if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) - { - WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu", error); - return error; - } - break; + if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) + { + WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu", error); + return error; + } + break; - case PAKID_CORE_DEVICE_REPLY: - /* connect to a specific resource */ - Stream_Read_UINT32(s, deviceId); - Stream_Read_UINT32(s, status); - break; + case PAKID_CORE_USER_LOGGEDON: + if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) + { + WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu", error); + return error; + } + break; - case PAKID_CORE_DEVICE_IOREQUEST: - if ((error = rdpdr_process_irp(rdpdr, s))) - { - WLog_ERR(TAG, "rdpdr_process_irp failed with error %lu", error); - return error; - } - s = NULL; - break; - - default: - WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04X", packetId); + case PAKID_CORE_DEVICE_REPLY: + /* connect to a specific resource */ + if (Stream_GetRemainingLength(s) < 8) return ERROR_INVALID_DATA; - break; + + Stream_Read_UINT32(s, deviceId); + Stream_Read_UINT32(s, status); + break; + + case PAKID_CORE_DEVICE_IOREQUEST: + if ((error = rdpdr_process_irp(rdpdr, s))) + { + WLog_ERR(TAG, "rdpdr_process_irp failed with error %lu", error); + return error; + } + s = NULL; + break; + + default: + WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04X", packetId); + return ERROR_INVALID_DATA; + break; } } @@ -999,21 +1021,24 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) { switch (packetId) { - case PAKID_PRN_CACHE_DATA: - { - UINT32 eventID; - Stream_Read_UINT32(s, eventID); - WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%04X)", eventID); - } - break; - - case PAKID_PRN_USING_XPS: - WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_USING_XPS"); - break; - - default: - WLog_ERR(TAG, "Unknown printing component packetID: 0x%04X", packetId); + case PAKID_PRN_CACHE_DATA: + { + UINT32 eventID; + if (Stream_GetRemainingLength(s) < 4) return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, eventID); + WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%04X)", eventID); + } + break; + + case PAKID_PRN_USING_XPS: + WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_USING_XPS"); + break; + + default: + WLog_ERR(TAG, "Unknown printing component packetID: 0x%04X", packetId); + return ERROR_INVALID_DATA; } } else @@ -1132,14 +1157,15 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) UINT status; rdpdrPlugin* plugin = (rdpdrPlugin*) rdpdr; + if (!rdpdr || !s) + return CHANNEL_RC_NULL_DATA; + if (!plugin) - { status = CHANNEL_RC_BAD_INIT_HANDLE; - } else { status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle, - Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); + Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); } if (status != CHANNEL_RC_OK) @@ -1158,7 +1184,7 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) * @return 0 on success, otherwise a Win32 error code */ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; @@ -1190,7 +1216,7 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); - return CHANNEL_RC_NO_MEMORY; + return ERROR_INVALID_DATA; } Stream_Write(data_in, pData, dataLength); @@ -1216,14 +1242,14 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, } static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT event, - LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpdrPlugin* rdpdr; UINT error = CHANNEL_RC_OK; rdpdr = (rdpdrPlugin*) rdpdr_get_open_handle_data(openHandle); - if (!rdpdr) + if (!rdpdr || !pData) { WLog_ERR(TAG, "rdpdr_virtual_channel_open_event: error no match"); return; @@ -1231,17 +1257,17 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT ev switch (event) { - case CHANNEL_EVENT_DATA_RECEIVED: - if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags))) - WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received failed with error %lu!", error ); - break; + case CHANNEL_EVENT_DATA_RECEIVED: + if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received failed with error %lu!", error ); + break; - case CHANNEL_EVENT_WRITE_COMPLETE: - Stream_Free((wStream*) pData, TRUE); - break; + case CHANNEL_EVENT_WRITE_COMPLETE: + Stream_Free((wStream*) pData, TRUE); + break; - case CHANNEL_EVENT_USER: - break; + case CHANNEL_EVENT_USER: + break; } if (error && rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_open_event reported an error"); @@ -1256,6 +1282,12 @@ static void* rdpdr_virtual_channel_client_thread(void* arg) rdpdrPlugin* rdpdr = (rdpdrPlugin*) arg; UINT error; + if (!rdpdr) + { + ExitThread((DWORD) CHANNEL_RC_NULL_DATA); + return NULL; + } + if ((error = rdpdr_process_connect(rdpdr))) { WLog_ERR(TAG, "rdpdr_process_connect failed with error %lu!", error); @@ -1305,16 +1337,16 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa UINT error; status = rdpdr->channelEntryPoints.pVirtualChannelOpen(rdpdr->InitHandle, - &rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event); + &rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event); - if (status != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]", - WTSErrorToString(status), status); - return status; - } + if (status != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]", + WTSErrorToString(status), status); + return status; + } - if ((error = rdpdr_add_open_handle_data(rdpdr->OpenHandle, rdpdr))) + if ((error = rdpdr_add_open_handle_data(rdpdr->OpenHandle, rdpdr))) { WLog_ERR(TAG, "rdpdr_add_open_handle_data failed with error %lu!", error); return error; @@ -1346,11 +1378,11 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) UINT error; if (MessageQueue_PostQuit(rdpdr->queue, 0) && (WaitForSingleObject(rdpdr->thread, INFINITE) == WAIT_FAILED)) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); - return error; - } + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); + return error; + } MessageQueue_Free(rdpdr->queue); CloseHandle(rdpdr->thread); @@ -1359,10 +1391,10 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) rdpdr->thread = NULL; if ((error = drive_hotplug_thread_terminate(rdpdr))) - { - WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %lu!", error); - return error; - } + { + WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %lu!", error); + return error; + } error = rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle); if (CHANNEL_RC_OK != error) @@ -1409,25 +1441,25 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT switch (event) { - case CHANNEL_EVENT_INITIALIZED: - break; - case CHANNEL_EVENT_CONNECTED: - if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) - WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!", error); - break; + case CHANNEL_EVENT_INITIALIZED: + break; + case CHANNEL_EVENT_CONNECTED: + if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!", error); + break; - case CHANNEL_EVENT_DISCONNECTED: - if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr))) - WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!", error); - break; + case CHANNEL_EVENT_DISCONNECTED: + if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!", error); + break; - case CHANNEL_EVENT_TERMINATED: - rdpdr_virtual_channel_event_terminated(rdpdr); - break; - default: - WLog_ERR(TAG, "unknown event %d!", event); - error = ERROR_INVALID_DATA; - break; + case CHANNEL_EVENT_TERMINATED: + rdpdr_virtual_channel_event_terminated(rdpdr); + break; + default: + WLog_ERR(TAG, "unknown event %d!", event); + error = ERROR_INVALID_DATA; + break; } if (error && rdpdr->rdpcontext) @@ -1444,7 +1476,6 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) rdpdrPlugin* rdpdr; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; - rdpdr = (rdpdrPlugin*) calloc(1, sizeof(rdpdrPlugin)); if (!rdpdr) @@ -1473,7 +1504,6 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); - rc = rdpdr->channelEntryPoints.pVirtualChannelInit(&rdpdr->InitHandle, &rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpdr_virtual_channel_init_event);