From 192680a0019ab7b2eb391860d311f84834d43dda Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 12 Dec 2018 10:06:41 +0100 Subject: [PATCH 1/5] 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; From d13bd66f5a112fc05e6445dfc60512a5416773ae Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 12 Dec 2018 14:10:46 +0100 Subject: [PATCH 2/5] Implemented printer name based backend to remember settings. --- channels/printer/client/printer_main.c | 633 ++++++++++++++++++++++--- 1 file changed, 573 insertions(+), 60 deletions(-) diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index c1c3ea839..4f6969aa1 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -35,8 +35,10 @@ #include #include #include +#include #include +#include #include "../printer.h" @@ -71,6 +73,417 @@ struct _PRINTER_DEVICE char port[64]; }; +typedef enum +{ + PRN_CONF_PORT = 0, + PRN_CONF_PNP = 1, + PRN_CONF_DRIVER = 2, + PRN_CONF_DATA = 3 +} +prn_conf_t; + +static const char* filemap[] = +{ + "PortDosName", + "PnPName", + "DriverName", + "CachedPrinterConfigData" +}; + +static char* get_printer_config_path(const rdpSettings* settings, const WCHAR* name, size_t length) +{ + char* dir = GetCombinedPath(settings->ConfigPath, "printers"); + char* bname = crypto_base64_encode((const BYTE*) name, (int)length); + char* config = GetCombinedPath(dir, bname); + + if (config && !PathFileExistsA(config)) + { + if (!PathMakePathA(config, NULL)) + { + free(config); + config = NULL; + } + } + + free(dir); + free(bname); + return config; +} + +static BOOL printer_write_setting(const char* path, prn_conf_t type, const void* data, + size_t length) +{ + DWORD written = 0; + BOOL rc = FALSE; + HANDLE file; + size_t b64len; + char* base64 = NULL; + const char* name = filemap[type]; + char* abs = GetCombinedPath(path, name); + + if (!abs) + return FALSE; + + file = CreateFileA(abs, GENERIC_WRITE, 0, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + free(abs); + + if (file == INVALID_HANDLE_VALUE) + return FALSE; + + if (length > 0) + { + base64 = crypto_base64_encode(data, length); + + if (!base64) + goto fail; + + b64len = strlen(base64); + rc = WriteFile(file, base64, b64len, &written, NULL); + + if (b64len != written) + rc = FALSE; + } + else + rc = TRUE; + +fail: + CloseHandle(file); + free(base64); + return rc; +} + +static BOOL printer_config_valid(const char* path) +{ + if (!path) + return FALSE; + + if (!PathFileExistsA(path)) + return FALSE; + + return TRUE; +} + +static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data, size_t* length) +{ + DWORD lowSize, highSize; + DWORD read = 0; + BOOL rc = FALSE; + HANDLE file; + BYTE* fdata = NULL; + const char* name = filemap[type]; + char* abs = GetCombinedPath(path, name); + + if (!abs) + return FALSE; + + file = CreateFileA(abs, GENERIC_READ, 0, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + free(abs); + + if (file == INVALID_HANDLE_VALUE) + return FALSE; + + lowSize = GetFileSize(file, &highSize); + + if ((lowSize == INVALID_FILE_SIZE) || (highSize != 0)) + goto fail; + + if (lowSize != 0) + { + fdata = malloc(lowSize); + + if (!fdata) + goto fail; + + rc = ReadFile(file, fdata, lowSize, &read, NULL); + + if (lowSize != read) + rc = FALSE; + } + +fail: + CloseHandle(file); + + if (rc) + { + int blen = 0; + crypto_base64_decode(fdata, lowSize, data, &blen); + + if (*data) + *length = blen; + else + { + rc = FALSE; + *length = 0; + } + } + else + { + *length = 0; + *data = NULL; + } + + free(fdata); + return rc; +} + +static BOOL printer_save_to_config(const rdpSettings* settings, + const char* PortDosName, size_t PortDosNameLen, + const WCHAR* PnPName, size_t PnPNameLen, + const WCHAR* DriverName, size_t DriverNameLen, + const WCHAR* PrinterName, size_t PrintNameLen, + const BYTE* CachedPrinterConfigData, size_t CacheFieldsLen) +{ + BOOL rc = FALSE; + char* path = get_printer_config_path(settings, PrinterName, PrintNameLen); + + if (!path) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_PORT, PortDosName, PortDosNameLen)) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_PNP, PnPName, PnPNameLen)) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_DRIVER, DriverName, DriverNameLen)) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_DATA, CachedPrinterConfigData, CacheFieldsLen)) + goto fail; + +fail: + free(path); + return rc; +} + +static BOOL printer_update_to_config(const rdpSettings* settings, const WCHAR* name, size_t length, + const BYTE* data, size_t datalen) +{ + BOOL rc = FALSE; + char* path = get_printer_config_path(settings, name, length); + rc = printer_write_setting(path, PRN_CONF_DATA, data, datalen); + free(path); + return rc; +} + +static BOOL printer_remove_config(const rdpSettings* settings, const WCHAR* name, size_t length) +{ + BOOL rc = FALSE; + char* path = get_printer_config_path(settings, name, length); + + if (!printer_config_valid(path)) + goto fail; + + rc = RemoveDirectoryA(path); +fail: + free(path); + return rc; +} + +static BOOL printer_move_config(const rdpSettings* settings, const WCHAR* oldName, size_t oldLength, + const WCHAR* newName, size_t newLength) +{ + BOOL rc = FALSE; + char* oldPath = get_printer_config_path(settings, oldName, oldLength); + char* newPath = get_printer_config_path(settings, newName, newLength); + + if (printer_config_valid(oldPath)) + rc = MoveFileA(oldPath, newPath); + + free(oldPath); + free(newPath); + return rc; +} + +#if 0 +sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%d", printer->id); +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; +CachedFieldsLen = 0; +CachedPrinterConfigData = NULL; +Flags = 0; + +if (printer->is_default) + Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER; + +DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName, + 0) * 2; +PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName, + 0) * 2; +printer_dev->device.data = Stream_New(NULL, + 28 + DriverNameLen + PrintNameLen + CachedFieldsLen); + +if (!printer_dev->device.data) +{ + WLog_ERR(TAG, "calloc failed!"); + error = CHANNEL_RC_NO_MEMORY; + free(DriverName); + free(PrintName); + goto error_out; +} + +Stream_Write_UINT32(printer_dev->device.data, Flags); +Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */ +Stream_Write_UINT32(printer_dev->device.data, printer_dev->PnPNameLen); /* PnPNameLen */ +Stream_Write_UINT32(printer_dev->device.data, DriverNameLen + 2); +Stream_Write_UINT32(printer_dev->device.data, PrintNameLen + 2); +Stream_Write_UINT32(printer_dev->device.data, printer_dev->CachedFieldsLen); +Stream_Write(printer_dev->device.data, DriverName, DriverNameLen); +Stream_Write_UINT16(printer_dev->device.data, 0); +Stream_Write(printer_dev->device.data, PrintName, PrintNameLen); +Stream_Write_UINT16(printer_dev->device.data, 0); + +if (printer_dev->PnPNameLen > 0) + Stream_Write(printer_dev->device.data, printer_dev->PnPName, printer_dev->PnPNameLen); + +if (printer_dev->CachedFieldsLen > 0) + Stream_Write(printer_dev->device.data, printer_dev->CachedPrinterConfigData, + printer_dev->CachedFieldsLen); + +free(DriverName); +free(PrintName); +#endif +static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* printer, + PRINTER_DEVICE* printer_dev) +{ + BOOL res = FALSE; + WCHAR* wname = NULL; + size_t wlen; + char* path = NULL; + int rc; + UINT32 flags = 0; + WCHAR* DriverName = NULL; + size_t DriverNameLen = 0; + WCHAR* PnPName = NULL; + size_t PnPNameLen = 0; + BYTE* CachedPrinterConfigData = NULL; + size_t CachedFieldsLen = 0; + size_t PrinterNameLen = 0; + + if (!settings || !printer) + return FALSE; + + rc = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &wname, 0); + + if (rc <= 0) + goto fail; + + wlen = _wcslen(wname) + 1; + path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR)); + PrinterNameLen = (wlen + 1) * sizeof(WCHAR); + + if (!path) + goto fail; + + if (printer->is_default) + flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER; + + if (!printer_read_setting(path, PRN_CONF_PNP, &PnPName, &PnPNameLen)) + { + } + + if (!printer_read_setting(path, PRN_CONF_DRIVER, &DriverName, &DriverNameLen)) + { + DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName, + 0) * 2 + 1; + } + + if (!printer_read_setting(path, PRN_CONF_DATA, &CachedPrinterConfigData, &CachedFieldsLen)) + { + } + + Stream_SetPosition(printer_dev->device.data, 0); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, 24)) + goto fail; + + Stream_Write_UINT32(printer_dev->device.data, flags); + Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */ + Stream_Write_UINT32(printer_dev->device.data, PnPNameLen); /* PnPNameLen */ + Stream_Write_UINT32(printer_dev->device.data, DriverNameLen); + Stream_Write_UINT32(printer_dev->device.data, PrinterNameLen); + Stream_Write_UINT32(printer_dev->device.data, CachedFieldsLen); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, PnPNameLen)) + goto fail; + + if (PnPNameLen > 0) + Stream_Write(printer_dev->device.data, PnPName, PnPNameLen); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, DriverNameLen)) + goto fail; + + Stream_Write(printer_dev->device.data, DriverName, DriverNameLen); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, PrinterNameLen)) + goto fail; + + Stream_Write(printer_dev->device.data, wname, PrinterNameLen); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, CachedFieldsLen)) + goto fail; + + Stream_Write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen); + res = TRUE; +fail: + free(path); + free(wname); + free(PnPName); + free(DriverName); + free(CachedPrinterConfigData); + return res; +} + +static BOOL printer_save_default_config(const rdpSettings* settings, rdpPrinter* printer) +{ + BOOL res = FALSE; + WCHAR* wname = NULL; + WCHAR* driver = NULL; + size_t wlen, dlen; + char* path = NULL; + int rc; + + if (!settings || !printer) + return FALSE; + + rc = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &wname, 0); + + if (rc <= 0) + goto fail; + + rc = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &driver, 0); + + if (rc <= 0) + goto fail; + + wlen = _wcslen(wname) + 1; + dlen = _wcslen(driver) + 1; + path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR)); + + if (!path) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_DRIVER, driver, dlen * sizeof(WCHAR))) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_DATA, NULL, 0)) + goto fail; + + res = TRUE; +fail: + free(path); + free(wname); + free(driver); + return res; +} + /** * Function description * @@ -295,36 +708,174 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp) static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 packetId, wStream* s) { - switch (component) + UINT32 eventID; + PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device; + const rdpSettings* settings = printer_dev->rdpcontext->settings; + + if (component != RDPDR_CTYP_PRN) + return ERROR_INVALID_DATA; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, eventID); + + switch (packetId) { - case RDPDR_CTYP_PRN: - switch (packetId) + case PAKID_PRN_CACHE_DATA: + switch (eventID) { - case PAKID_PRN_CACHE_DATA: + case RDPDR_ADD_PRINTER_EVENT: { - UINT32 eventID; + char PortDosName[8]; + UINT32 PnPNameLen, DriverNameLen, PrintNameLen, CacheFieldsLen; + const WCHAR* PnPName, *DriverName, *PrinterName; + const BYTE* CachedPrinterConfigData; + + if (Stream_GetRemainingLength(s) < 24) + return ERROR_INVALID_DATA; + + Stream_Read(s, PortDosName, sizeof(PortDosName)); + Stream_Read_UINT32(s, PnPNameLen); + Stream_Read_UINT32(s, DriverNameLen); + Stream_Read_UINT32(s, PrintNameLen); + Stream_Read_UINT32(s, CacheFieldsLen); + + if (Stream_GetRemainingLength(s) < PnPNameLen) + return ERROR_INVALID_DATA; + + PnPName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, PnPNameLen); + + if (Stream_GetRemainingLength(s) < DriverNameLen) + return ERROR_INVALID_DATA; + + DriverName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, DriverNameLen); + + if (Stream_GetRemainingLength(s) < PrintNameLen) + return ERROR_INVALID_DATA; + + PrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, PrintNameLen); + + if (Stream_GetRemainingLength(s) < CacheFieldsLen) + return ERROR_INVALID_DATA; + + CachedPrinterConfigData = Stream_Pointer(s); + Stream_Seek(s, CacheFieldsLen); + + if (!printer_save_to_config(settings, + PortDosName, sizeof(PortDosName), + PnPName, PnPNameLen, + DriverName, DriverNameLen, + PrinterName, PrintNameLen, + CachedPrinterConfigData, CacheFieldsLen)) + return ERROR_INTERNAL_ERROR; + } + break; + + case RDPDR_UPDATE_PRINTER_EVENT: + { + UINT32 PrinterNameLen, ConfigDataLen; + const WCHAR* PrinterName; + const BYTE* ConfigData; + + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, PrinterNameLen); + Stream_Read_UINT32(s, ConfigDataLen); + + if (Stream_GetRemainingLength(s) < PrinterNameLen) + return ERROR_INVALID_DATA; + + PrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, PrinterNameLen); + + if (Stream_GetRemainingLength(s) < ConfigDataLen) + return ERROR_INVALID_DATA; + + ConfigData = Stream_Pointer(s); + Stream_Seek(s, ConfigDataLen); + + if (!printer_update_to_config(settings, PrinterName, PrinterNameLen, ConfigData, ConfigDataLen)) + return ERROR_INTERNAL_ERROR; + } + break; + + case RDPDR_DELETE_PRINTER_EVENT: + { + UINT32 PrinterNameLen; + const WCHAR* PrinterName; 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); + Stream_Read_UINT32(s, PrinterNameLen); + + if (Stream_GetRemainingLength(s) < PrinterNameLen) + return ERROR_INVALID_DATA; + + PrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, PrinterNameLen); + printer_remove_config(settings, PrinterName, PrinterNameLen); } break; - case PAKID_PRN_USING_XPS: - WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_USING_XPS"); + case RDPDR_RENAME_PRINTER_EVENT: + { + UINT32 OldPrinterNameLen, NewPrinterNameLen; + const WCHAR* OldPrinterName; + const WCHAR* NewPrinterName; + + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, OldPrinterNameLen); + Stream_Read_UINT32(s, NewPrinterNameLen); + + if (Stream_GetRemainingLength(s) < OldPrinterNameLen) + return ERROR_INVALID_DATA; + + OldPrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, OldPrinterNameLen); + + if (Stream_GetRemainingLength(s) < NewPrinterNameLen) + return ERROR_INVALID_DATA; + + NewPrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, NewPrinterNameLen); + + if (!printer_move_config(settings, OldPrinterName, OldPrinterNameLen, NewPrinterName, + NewPrinterNameLen)) + return ERROR_INTERNAL_ERROR; + } break; default: - WLog_ERR(TAG, "Unknown printing component packetID: 0x%04"PRIX16"", packetId); + WLog_ERR(TAG, "Unknown chache data eventID: 0x%08"PRIX32"", eventID); return ERROR_INVALID_DATA; } break; + case PAKID_PRN_USING_XPS: + { + UINT32 flags; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, flags); + WLog_ERR(TAG, + "Ignoring unhandled message PAKID_PRN_USING_XPS [printerID=%08"PRIx32", flags=%08"PRIx32"]", + eventID, flags); + } + break; + default: + WLog_ERR(TAG, "Unknown printing component packetID: 0x%04"PRIX16"", packetId); return ERROR_INVALID_DATA; } @@ -374,13 +925,6 @@ static UINT printer_free(DEVICE* device) UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* printer) { - UINT32 Flags; - int DriverNameLen; - WCHAR* DriverName = NULL; - int PrintNameLen; - WCHAR* PrintName = NULL; - UINT32 CachedFieldsLen; - BYTE* CachedPrinterConfigData; PRINTER_DEVICE* printer_dev; UINT error; printer_dev = (PRINTER_DEVICE*) calloc(1, sizeof(PRINTER_DEVICE)); @@ -391,6 +935,11 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, return CHANNEL_RC_NO_MEMORY; } + printer_dev->device.data = Stream_New(NULL, 1024); + + if (!printer_dev->device.data) + goto error_out; + sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%d", printer->id); printer_dev->device.type = RDPDR_DTYP_PRINT; printer_dev->device.name = printer_dev->port; @@ -399,48 +948,6 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, printer_dev->device.Free = printer_free; printer_dev->rdpcontext = pEntryPoints->rdpcontext; printer_dev->printer = printer; - CachedFieldsLen = 0; - CachedPrinterConfigData = NULL; - Flags = 0; - - if (printer->is_default) - Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER; - - DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName, - 0) * 2; - PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName, - 0) * 2; - printer_dev->device.data = Stream_New(NULL, - 28 + DriverNameLen + PrintNameLen + CachedFieldsLen); - - if (!printer_dev->device.data) - { - WLog_ERR(TAG, "calloc failed!"); - error = CHANNEL_RC_NO_MEMORY; - free(DriverName); - free(PrintName); - goto error_out; - } - - Stream_Write_UINT32(printer_dev->device.data, Flags); - Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */ - Stream_Write_UINT32(printer_dev->device.data, 0); /* PnPNameLen */ - Stream_Write_UINT32(printer_dev->device.data, DriverNameLen + 2); - Stream_Write_UINT32(printer_dev->device.data, PrintNameLen + 2); - Stream_Write_UINT32(printer_dev->device.data, CachedFieldsLen); - Stream_Write(printer_dev->device.data, DriverName, DriverNameLen); - Stream_Write_UINT16(printer_dev->device.data, 0); - Stream_Write(printer_dev->device.data, PrintName, PrintNameLen); - Stream_Write_UINT16(printer_dev->device.data, 0); - - if (CachedFieldsLen > 0) - { - Stream_Write(printer_dev->device.data, CachedPrinterConfigData, - CachedFieldsLen); - } - - free(DriverName); - free(PrintName); printer_dev->pIrpList = (WINPR_PSLIST_HEADER) _aligned_malloc(sizeof( WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT); @@ -451,6 +958,9 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, goto error_out; } + if (!printer_load_from_config(pEntryPoints->rdpcontext->settings, printer, printer_dev)) + goto error_out; + InitializeSListHead(printer_dev->pIrpList); if (!(printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL))) @@ -536,6 +1046,9 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) return CHANNEL_RC_INITIALIZATION_ERROR; } + if (!printer_save_default_config(pEntryPoints->rdpcontext->settings, printer)) + return CHANNEL_RC_INITIALIZATION_ERROR; + if ((error = printer_register(pEntryPoints, printer))) { WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error); From 31d5a3b0c354cb96751d1a0059250b84883dffb2 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 12 Dec 2018 14:42:50 +0100 Subject: [PATCH 3/5] Don't reset configuration and driver name when supplied via command line. --- channels/printer/client/printer_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 4f6969aa1..5c386d72d 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -470,11 +470,11 @@ static BOOL printer_save_default_config(const rdpSettings* settings, rdpPrinter* if (!path) goto fail; - if (!printer_write_setting(path, PRN_CONF_DRIVER, driver, dlen * sizeof(WCHAR))) - goto fail; - - if (!printer_write_setting(path, PRN_CONF_DATA, NULL, 0)) - goto fail; + if (dlen > 1) + { + if (!printer_write_setting(path, PRN_CONF_DRIVER, driver, dlen * sizeof(WCHAR))) + goto fail; + } res = TRUE; fail: From 34c9404c9899eec63025623f80bb42606b04a792 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 12 Dec 2018 15:40:50 +0100 Subject: [PATCH 4/5] Added OpenSSL include path globally. --- CMakeLists.txt | 1 + channels/printer/client/printer_cups.c | 2 +- channels/printer/client/printer_main.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ecad9444..046965128 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -934,6 +934,7 @@ endif() if(OPENSSL_FOUND) add_definitions("-DWITH_OPENSSL") message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}") + include_directories(${OPENSSL_INCLUDE_DIR}) endif() if(MBEDTLS_FOUND) diff --git a/channels/printer/client/printer_cups.c b/channels/printer/client/printer_cups.c index d6f0705d6..8af8752c3 100644 --- a/channels/printer/client/printer_cups.c +++ b/channels/printer/client/printer_cups.c @@ -84,7 +84,7 @@ static void printer_cups_get_printjob_name(char* buf, int size) * * @return 0 on success, otherwise a Win32 error code */ -static UINT printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int size) +static UINT printer_cups_write_printjob(rdpPrintJob* printjob, const BYTE* data, size_t size) { rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob; diff --git a/channels/printer/client/printer_main.h b/channels/printer/client/printer_main.h index dfb56d8e0..07bd60854 100644 --- a/channels/printer/client/printer_main.h +++ b/channels/printer/client/printer_main.h @@ -54,7 +54,7 @@ struct rdp_printer pcFreePrinter Free; }; -typedef UINT (*pcWritePrintJob) (rdpPrintJob* printjob, BYTE* data, int size); +typedef UINT (*pcWritePrintJob) (rdpPrintJob* printjob, const BYTE* data, size_t size); typedef void (*pcClosePrintJob) (rdpPrintJob* printjob); struct rdp_print_job From dd9814df8499b19db109e76e95dd9c2596aa82fb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 29 Jan 2019 14:21:58 +0100 Subject: [PATCH 5/5] Fixed review remarks. --- channels/printer/client/printer_main.c | 55 +------------------------- 1 file changed, 1 insertion(+), 54 deletions(-) diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 5c386d72d..b8bd7e8a9 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -297,59 +297,6 @@ static BOOL printer_move_config(const rdpSettings* settings, const WCHAR* oldNam return rc; } -#if 0 -sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%d", printer->id); -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; -CachedFieldsLen = 0; -CachedPrinterConfigData = NULL; -Flags = 0; - -if (printer->is_default) - Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER; - -DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName, - 0) * 2; -PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName, - 0) * 2; -printer_dev->device.data = Stream_New(NULL, - 28 + DriverNameLen + PrintNameLen + CachedFieldsLen); - -if (!printer_dev->device.data) -{ - WLog_ERR(TAG, "calloc failed!"); - error = CHANNEL_RC_NO_MEMORY; - free(DriverName); - free(PrintName); - goto error_out; -} - -Stream_Write_UINT32(printer_dev->device.data, Flags); -Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */ -Stream_Write_UINT32(printer_dev->device.data, printer_dev->PnPNameLen); /* PnPNameLen */ -Stream_Write_UINT32(printer_dev->device.data, DriverNameLen + 2); -Stream_Write_UINT32(printer_dev->device.data, PrintNameLen + 2); -Stream_Write_UINT32(printer_dev->device.data, printer_dev->CachedFieldsLen); -Stream_Write(printer_dev->device.data, DriverName, DriverNameLen); -Stream_Write_UINT16(printer_dev->device.data, 0); -Stream_Write(printer_dev->device.data, PrintName, PrintNameLen); -Stream_Write_UINT16(printer_dev->device.data, 0); - -if (printer_dev->PnPNameLen > 0) - Stream_Write(printer_dev->device.data, printer_dev->PnPName, printer_dev->PnPNameLen); - -if (printer_dev->CachedFieldsLen > 0) - Stream_Write(printer_dev->device.data, printer_dev->CachedPrinterConfigData, - printer_dev->CachedFieldsLen); - -free(DriverName); -free(PrintName); -#endif static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* printer, PRINTER_DEVICE* printer_dev) { @@ -854,7 +801,7 @@ static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 pa break; default: - WLog_ERR(TAG, "Unknown chache data eventID: 0x%08"PRIX32"", eventID); + WLog_ERR(TAG, "Unknown cache data eventID: 0x%08"PRIX32"", eventID); return ERROR_INVALID_DATA; }