From 192680a0019ab7b2eb391860d311f84834d43dda Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 12 Dec 2018 10:06:41 +0100 Subject: [PATCH] Added callback to handle printer custom components in printer backend. --- channels/printer/client/printer_main.c | 39 +++++ channels/rdpdr/client/devman.c | 43 ++++- channels/rdpdr/client/devman.h | 1 + channels/rdpdr/client/rdpdr_main.c | 219 ++++++++++++------------- include/freerdp/channels/rdpdr.h | 3 + 5 files changed, 189 insertions(+), 116 deletions(-) diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 630c0c06d..c1c3ea839 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -293,6 +293,44 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp) return CHANNEL_RC_OK; } +static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 packetId, wStream* s) +{ + switch (component) + { + case RDPDR_CTYP_PRN: + switch (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%08"PRIX32")", 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%04"PRIX16"", packetId); + return ERROR_INVALID_DATA; + } + + break; + + default: + return ERROR_INVALID_DATA; + } + + return CHANNEL_RC_OK; +} + /** * Function description * @@ -357,6 +395,7 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, printer_dev->device.type = RDPDR_DTYP_PRINT; printer_dev->device.name = printer_dev->port; printer_dev->device.IRPRequest = printer_irp_request; + printer_dev->device.CustomComponentRequest = printer_custom_component; printer_dev->device.Free = printer_free; printer_dev->rdpcontext = pEntryPoints->rdpcontext; printer_dev->printer = printer; diff --git a/channels/rdpdr/client/devman.c b/channels/rdpdr/client/devman.c index 93db1b70b..67d83a9fe 100644 --- a/channels/rdpdr/client/devman.c +++ b/channels/rdpdr/client/devman.c @@ -68,8 +68,8 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr) devman->plugin = (void*) rdpdr; devman->id_sequence = 1; - devman->devices = ListDictionary_New(TRUE); + if (!devman->devices) { WLog_INFO(TAG, "ListDictionary_New failed!"); @@ -78,7 +78,6 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr) } ListDictionary_ValueObject(devman->devices)->fnObjectFree = devman_device_free; - return devman; } @@ -114,26 +113,57 @@ static UINT devman_register_device(DEVMAN* devman, DEVICE* device) return ERROR_INVALID_PARAMETER; device->id = devman->id_sequence++; - key = (void*) (size_t) device->id; + key = (void*)(size_t) device->id; if (!ListDictionary_Add(devman->devices, key, device)) { WLog_INFO(TAG, "ListDictionary_Add failed!"); return ERROR_INTERNAL_ERROR; } + return CHANNEL_RC_OK; } DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id) { DEVICE* device = NULL; - void* key = (void*) (size_t) id; + void* key = (void*)(size_t) id; if (!devman) return NULL; device = (DEVICE*) ListDictionary_GetItemValue(devman->devices, key); + return device; +} +DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type) +{ + DEVICE* device = NULL; + ULONG_PTR* keys; + int count, x; + + if (!devman) + return NULL; + + ListDictionary_Lock(devman->devices); + count = ListDictionary_GetKeys(devman->devices, &keys); + + for (x = 0; x < count; x++) + { + DEVICE* cur = (DEVICE*) ListDictionary_GetItemValue(devman->devices, keys[x]); + + if (!cur) + continue; + + if (cur->type != type) + continue; + + device = cur; + break; + } + + free(keys); + ListDictionary_Unlock(devman->devices); return device; } @@ -178,7 +208,9 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext WLog_INFO(TAG, "Loading device service %s [%s] (static)", ServiceName, device->Name); else WLog_INFO(TAG, "Loading device service %s (static)", ServiceName); - entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0); + + entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, + "DeviceServiceEntry", 0); if (!entry) { @@ -190,6 +222,5 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext ep.RegisterDevice = devman_register_device; ep.device = device; ep.rdpcontext = rdpcontext; - return entry(&ep); } diff --git a/channels/rdpdr/client/devman.h b/channels/rdpdr/client/devman.h index c99a17940..060038c9b 100644 --- a/channels/rdpdr/client/devman.h +++ b/channels/rdpdr/client/devman.h @@ -28,6 +28,7 @@ void devman_unregister_device(DEVMAN* devman, void* key); UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext); DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id); +DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type); DEVMAN* devman_new(rdpdrPlugin* rdpdr); void devman_free(DEVMAN* devman); diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 602268fe8..4f1a4ac8e 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -135,7 +135,8 @@ BOOL check_path(char* path) { UINT type = GetDriveTypeA(path); - if (!(type == DRIVE_FIXED ||type == DRIVE_REMOVABLE || type == DRIVE_CDROM || type == DRIVE_REMOTE)) + if (!(type == DRIVE_FIXED || type == DRIVE_REMOVABLE || type == DRIVE_CDROM || + type == DRIVE_REMOTE)) return FALSE; return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0); @@ -1324,6 +1325,31 @@ static UINT rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s) return error; } +static UINT rdpdr_process_component(rdpdrPlugin* rdpdr, UINT16 component, UINT16 packetId, + wStream* s) +{ + UINT32 type; + DEVICE* device; + + switch (component) + { + case RDPDR_CTYP_PRN: + type = RDPDR_DTYP_PRINT; + break; + + default: + return ERROR_INVALID_DATA; + } + + device = devman_get_device_by_type(rdpdr->devman, type); + + if (!device) + return ERROR_INVALID_PARAMETER; + + return IFCALLRESULT(ERROR_INVALID_PARAMETER, device->CustomComponentRequest, device, component, + packetId, s); +} + /** * Function description * @@ -1368,141 +1394,114 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) UINT16 packetId; UINT32 deviceId; UINT32 status; - UINT error; + UINT error = ERROR_INVALID_DATA; 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) */ - - if (component == RDPDR_CTYP_CORE) + if (Stream_GetRemainingLength(s) >= 4) { - switch (packetId) + Stream_Read_UINT16(s, component); /* Component (2 bytes) */ + Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */ + + if (component == RDPDR_CTYP_CORE) { - case PAKID_CORE_SERVER_ANNOUNCE: - if ((error = rdpdr_process_server_announce_request(rdpdr, s))) - return error; + switch (packetId) + { + case PAKID_CORE_SERVER_ANNOUNCE: + if ((error = rdpdr_process_server_announce_request(rdpdr, s))) + { + } + else if ((error = rdpdr_send_client_announce_reply(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %"PRIu32"", error); + } + else if ((error = rdpdr_send_client_name_request(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %"PRIu32"", error); + } + else if ((error = rdpdr_process_init(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_process_init failed with error %"PRIu32"", error); + } - if ((error = rdpdr_send_client_announce_reply(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %"PRIu32"", error); - return error; - } + break; - if ((error = rdpdr_send_client_name_request(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %"PRIu32"", error); - return error; - } + case PAKID_CORE_SERVER_CAPABILITY: + if ((error = rdpdr_process_capability_request(rdpdr, s))) + { + } + else if ((error = rdpdr_send_capability_response(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %"PRIu32"", error); + } - if ((error = rdpdr_process_init(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_process_init failed with error %"PRIu32"", error); - return error; - } + break; - break; + case PAKID_CORE_CLIENTID_CONFIRM: + if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s))) + { + } + else if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) + { + WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"", + error); + } - case PAKID_CORE_SERVER_CAPABILITY: - if ((error = rdpdr_process_capability_request(rdpdr, s))) - return error; + break; - if ((error = rdpdr_send_capability_response(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %"PRIu32"", error); - 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 %"PRIu32"", + error); + } - break; + break; - case PAKID_CORE_CLIENTID_CONFIRM: - if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s))) - return error; + case PAKID_CORE_DEVICE_REPLY: - if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) - { - WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"", - error); - return error; - } + /* connect to a specific resource */ + if (Stream_GetRemainingLength(s) >= 8) + { + Stream_Read_UINT32(s, deviceId); + Stream_Read_UINT32(s, status); + error = CHANNEL_RC_OK; + } - break; + 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 %"PRIu32"", - error); - return error; - } + case PAKID_CORE_DEVICE_IOREQUEST: + if ((error = rdpdr_process_irp(rdpdr, s))) + { + WLog_ERR(TAG, "rdpdr_process_irp failed with error %"PRIu32"", error); + return error; + } + else + s = NULL; - break; + break; - case PAKID_CORE_DEVICE_REPLY: - - /* connect to a specific resource */ - if (Stream_GetRemainingLength(s) < 8) - return ERROR_INVALID_DATA; - - 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 %"PRIu32"", error); - return error; - } - - s = NULL; - break; - - default: - WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04"PRIX16"", packetId); - return ERROR_INVALID_DATA; - break; + default: + WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04"PRIX16"", packetId); + error = ERROR_INVALID_DATA; + break; + } } - } - else if (component == RDPDR_CTYP_PRN) - { - switch (packetId) + else { - case PAKID_PRN_CACHE_DATA: - { - UINT32 eventID; + error = rdpdr_process_component(rdpdr, component, packetId, s); - 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%08"PRIX32")", 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%04"PRIX16"", packetId); - return ERROR_INVALID_DATA; + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "Unknown message: Component: 0x%04"PRIX16" PacketId: 0x%04"PRIX16"", component, + packetId); + } } } - else - { - WLog_ERR(TAG, "Unknown message: Component: 0x%04"PRIX16" PacketId: 0x%04"PRIX16"", component, - packetId); - return ERROR_INVALID_DATA; - } Stream_Free(s, TRUE); - return CHANNEL_RC_OK; + return error; } /** diff --git a/include/freerdp/channels/rdpdr.h b/include/freerdp/channels/rdpdr.h index b64ca26c4..b40ae2a5d 100644 --- a/include/freerdp/channels/rdpdr.h +++ b/include/freerdp/channels/rdpdr.h @@ -316,6 +316,8 @@ typedef struct _DEVICE DEVICE; typedef struct _IRP IRP; typedef struct _DEVMAN DEVMAN; +typedef UINT(*pcCustomComponentRequest)(DEVICE* device, UINT16 component, UINT16 packetId, + wStream* s); typedef UINT(*pcIRPRequest)(DEVICE* device, IRP* irp); typedef UINT(*pcInitDevice)(DEVICE* device); typedef UINT(*pcFreeDevice)(DEVICE* device); @@ -328,6 +330,7 @@ struct _DEVICE const char* name; wStream* data; + pcCustomComponentRequest CustomComponentRequest; pcIRPRequest IRPRequest; pcInitDevice Init; pcFreeDevice Free;