diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index 1b5422522..920a7918f 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -1017,7 +1018,12 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) char* bufdup; char* devdup; #endif + + WINPR_ASSERT(pEntryPoints); + drive = (RDPDR_DRIVE*)pEntryPoints->device; + WINPR_ASSERT(drive); + #ifndef WIN32 sys_code_page = CP_UTF8; @@ -1045,7 +1051,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) } } - error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path, drive->automount); + error = + drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path, drive->automount); #else sys_code_page = GetACP(); @@ -1064,7 +1071,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) return CHANNEL_RC_NO_MEMORY; } - error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path, drive->automount); + error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path, + drive->automount); } else if (strcmp(drive->Path, "*") == 0) { @@ -1077,7 +1085,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) if (*dev > 'B') { /* Suppress disk drives A and B to avoid pesty messages */ - len = sprintf_s(buf, sizeof(buf) - 4, "%s", drive->Name); + len = sprintf_s(buf, sizeof(buf) - 4, "%s", drive->device.Name); buf[len] = '_'; buf[len + 1] = dev[0]; buf[len + 2] = 0; @@ -1104,7 +1112,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) } else { - error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path, drive->automount); + error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path, + drive->automount); } #endif diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index af3e82703..dc2d59f89 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -47,6 +47,7 @@ #endif #include +#include #include #include #include @@ -424,8 +425,13 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) RDPDR_PARALLEL* device; PARALLEL_DEVICE* parallel; UINT error; + + WINPR_ASSERT(pEntryPoints); + device = (RDPDR_PARALLEL*)pEntryPoints->device; - name = device->Name; + WINPR_ASSERT(device); + + name = device->device.Name; path = device->Path; if (!name || (name[0] == '*') || !path) diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 71d8080d0..f18c953ef 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -982,7 +982,7 @@ printer_DeviceServiceEntry return ERROR_INVALID_PARAMETER; device = (RDPDR_PRINTER*)pEntryPoints->device; - name = device->Name; + name = device->device.Name; driver_name = _strdup(device->DriverName); /* Secondary argument is one of the following: diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 91748eaa5..82d60ef2a 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -127,6 +127,29 @@ static BOOL device_foreach(rdpdrPlugin* rdpdr, BOOL abortOnFail, */ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn); +static BOOL rdpdr_load_drive(rdpdrPlugin* rdpdr, const char* path, const char* name, BOOL automount) +{ + UINT rc = ERROR_INTERNAL_ERROR; + union + { + RDPDR_DRIVE* drive; + RDPDR_DEVICE* device; + } drive; + const char* args[] = { name, path, automount ? NULL : name }; + + drive.device = freerdp_device_new(RDPDR_DTYP_FILESYSTEM, ARRAYSIZE(args), args); + if (!drive.device) + goto fail; + + rc = devman_load_device_service(rdpdr->devman, drive.device, rdpdr->rdpcontext); + if (rc != CHANNEL_RC_OK) + goto fail; + +fail: + freerdp_device_free(drive.device); + return rc; +} + /** * Function description * @@ -199,18 +222,12 @@ static void first_hotplug(rdpdrPlugin* rdpdr) { char drive_path[] = { 'c', ':', '\\', '\0' }; char drive_name[] = { 'c', '\0' }; - RDPDR_DRIVE drive = { 0 }; drive_path[0] = 'A' + (char)i; drive_name[0] = 'A' + (char)i; if (check_path(drive_path)) { - drive.Type = RDPDR_DTYP_FILESYSTEM; - drive.Path = drive_path; - drive.Name = drive_name; - drive.automount = TRUE; - devman_load_device_service(rdpdr->devman, (const RDPDR_DEVICE*)&drive, - rdpdr->rdpcontext); + rdpdr_load_drive(rdpdr, drive_name, drive_path, TRUE); } } @@ -248,15 +265,7 @@ static LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM if (check_path(drive_path)) { - RDPDR_DRIVE drive = { 0 }; - - drive.Type = RDPDR_DTYP_FILESYSTEM; - drive.Path = drive_path; - drive.automount = TRUE; - drive.Name = drive_name; - devman_load_device_service(rdpdr->devman, - (const RDPDR_DEVICE*)&drive, - rdpdr->rdpcontext); + rdpdr_load_drive(rdpdr, drive_name, drive_path, TRUE); rdpdr_send_device_list_announce_request(rdpdr, TRUE); } } @@ -531,30 +540,14 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) /* add new devices */ for (i = 0; i < size; i++) { - if (dev_array[i].to_add) + const hotplug_dev* dev = &dev_array[i]; + if (dev->to_add) { - RDPDR_DRIVE drive = { 0 }; - char* name; - - drive.Type = RDPDR_DTYP_FILESYSTEM; - drive.Path = dev_array[i].path; - drive.automount = TRUE; - name = strrchr(drive.Path, '/') + 1; - drive.Name = name; - - if (!drive.Name) - { - error = CHANNEL_RC_NO_MEMORY; + const char* path = dev->path; + const char* name = strrchr(path, '/') + 1; + error = rdpdr_load_drive(rdpdr, name, path, TRUE); + if (error) goto cleanup; - } - - if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)&drive, - rdpdr->rdpcontext))) - { - WLog_ERR(TAG, "devman_load_device_service failed!"); - error = CHANNEL_RC_NO_MEMORY; - goto cleanup; - } } } @@ -929,34 +922,14 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) hotplug_dev* cur = &dev_array[i]; if (!device_already_plugged(rdpdr, cur)) { - RDPDR_DRIVE drive = { 0 }; - char* name; + const char* path = cur->path; + const char* name = strrchr(path, '/') + 1; - drive.Type = RDPDR_DTYP_FILESYSTEM; - drive.Path = cur->path; - drive.automount = TRUE; - name = strrchr(drive.Path, '/') + 1; - drive.Name = name; - - if (!drive.Name) - { - WLog_ERR(TAG, "_strdup failed!"); - error = CHANNEL_RC_NO_MEMORY; - goto cleanup; - } - - if ((error = devman_load_device_service(rdpdr->devman, (const RDPDR_DEVICE*)&drive, - rdpdr->rdpcontext))) - { - WLog_ERR(TAG, "devman_load_device_service failed!"); - goto cleanup; - } + rdpdr_load_drive(rdpdr, name, path, TRUE); error = ERROR_DISK_CHANGE; } } -cleanup: - for (i = 0; i < size; i++) free(dev_array[i].path); diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index c11076e3b..381c00625 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -823,8 +823,13 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) SERIAL_DEVICE* serial; #endif /* __linux__ */ UINT error = CHANNEL_RC_OK; + + WINPR_ASSERT(pEntryPoints); + device = (RDPDR_SERIAL*)pEntryPoints->device; - name = device->Name; + WINPR_ASSERT(device); + + name = device->device.Name; path = device->Path; driver = device->Driver; diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 4fef267fe..f09cabc20 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -145,14 +145,8 @@ static char* name_from_path(const char* path) static BOOL freerdp_client_add_drive(rdpSettings* settings, const char* path, const char* name) { - RDPDR_DRIVE* drive; - - drive = (RDPDR_DRIVE*)calloc(1, sizeof(RDPDR_DRIVE)); - - if (!drive) - return FALSE; - - drive->Type = RDPDR_DTYP_FILESYSTEM; + char* dname; + RDPDR_DEVICE* device = NULL; if (name) { @@ -169,36 +163,37 @@ static BOOL freerdp_client_add_drive(rdpSettings* settings, const char* path, co } if (name) - { - if (!(drive->Name = _strdup(name))) - goto fail; - } + dname = _strdup(name); else /* We need a name to send to the server. */ - { - if (!(drive->Name = name_from_path(path))) - goto fail; - } + dname = name_from_path(path); - if (!path || !freerdp_sanitize_drive_name(drive->Name, "\\/", "__")) + if (freerdp_sanitize_drive_name(dname, "\\/", "__")) + { + const char* args[] = { dname, path }; + device = freerdp_device_new(RDPDR_DTYP_FILESYSTEM, ARRAYSIZE(args), args); + } + free(dname); + if (!device) + return FALSE; + + if (!path) goto fail; else { BOOL isSpecial = FALSE; BOOL isPath = freerdp_path_valid(path, &isSpecial); - if ((!isPath && !isSpecial) || !(drive->Path = _strdup(path))) + if (!isPath && !isSpecial) goto fail; } - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*)drive)) + if (!freerdp_device_collection_add(settings, device)) goto fail; return TRUE; fail: - free(drive->Path); - free(drive->Name); - free(drive); + freerdp_device_free(device); return FALSE; } @@ -552,6 +547,10 @@ static int freerdp_client_command_line_pre_filter(void* context, int index, int BOOL freerdp_client_add_device_channel(rdpSettings* settings, size_t count, const char** params) { + WINPR_ASSERT(settings); + WINPR_ASSERT(params); + WINPR_ASSERT(count > 0); + if (strcmp(params[0], "drive") == 0) { BOOL rc; @@ -568,7 +567,7 @@ BOOL freerdp_client_add_device_channel(rdpSettings* settings, size_t count, cons } else if (strcmp(params[0], "printer") == 0) { - RDPDR_PRINTER* printer; + RDPDR_DEVICE* printer; if (count < 1) return FALSE; @@ -576,71 +575,36 @@ BOOL freerdp_client_add_device_channel(rdpSettings* settings, size_t count, cons settings->RedirectPrinters = TRUE; settings->DeviceRedirection = TRUE; - if (count > 1) + printer = freerdp_device_new(RDPDR_DTYP_PRINT, count - 1, ¶ms[1]); + if (!printer) + return FALSE; + + if (!freerdp_device_collection_add(settings, printer)) { - printer = (RDPDR_PRINTER*)calloc(1, sizeof(RDPDR_PRINTER)); - - if (!printer) - return FALSE; - - printer->Type = RDPDR_DTYP_PRINT; - - if (!(printer->Name = _strdup(params[1]))) - { - free(printer); - return FALSE; - } - - if (count > 2) - { - if (!(printer->DriverName = _strdup(params[2]))) - { - free(printer->Name); - free(printer); - return FALSE; - } - } - - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*)printer)) - { - free(printer->DriverName); - free(printer->Name); - free(printer); - return FALSE; - } + freerdp_device_free(printer); + return FALSE; } return TRUE; } else if (strcmp(params[0], "smartcard") == 0) { - RDPDR_SMARTCARD* smartcard; + RDPDR_DEVICE* smartcard; if (count < 1) return FALSE; settings->RedirectSmartCards = TRUE; settings->DeviceRedirection = TRUE; - smartcard = (RDPDR_SMARTCARD*)calloc(1, sizeof(RDPDR_SMARTCARD)); + + smartcard = freerdp_device_new(RDPDR_DTYP_SMARTCARD, count - 1, ¶ms[1]); if (!smartcard) return FALSE; - smartcard->Type = RDPDR_DTYP_SMARTCARD; - - if (count > 1 && strlen(params[1])) + if (!freerdp_device_collection_add(settings, smartcard)) { - if (!(smartcard->Name = _strdup(params[1]))) - { - free(smartcard); - return FALSE; - } - } - - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*)smartcard)) - { - free(smartcard->Name); - free(smartcard); + freerdp_device_free(smartcard); return FALSE; } @@ -648,69 +612,22 @@ BOOL freerdp_client_add_device_channel(rdpSettings* settings, size_t count, cons } else if (strcmp(params[0], "serial") == 0) { - RDPDR_SERIAL* serial; + RDPDR_DEVICE* serial; if (count < 1) return FALSE; settings->RedirectSerialPorts = TRUE; settings->DeviceRedirection = TRUE; - serial = (RDPDR_SERIAL*)calloc(1, sizeof(RDPDR_SERIAL)); + + serial = freerdp_device_new(RDPDR_DTYP_SERIAL, count - 1, ¶ms[1]); if (!serial) return FALSE; - serial->Type = RDPDR_DTYP_SERIAL; - - if (count > 1) + if (!freerdp_device_collection_add(settings, serial)) { - if (!(serial->Name = _strdup(params[1]))) - { - free(serial); - return FALSE; - } - } - - if (count > 2) - { - if (!(serial->Path = _strdup(params[2]))) - { - free(serial->Name); - free(serial); - return FALSE; - } - } - - if (count > 3) - { - if (!(serial->Driver = _strdup(params[3]))) - { - free(serial->Path); - free(serial->Name); - free(serial); - return FALSE; - } - } - - if (count > 4) - { - if (!(serial->Permissive = _strdup(params[4]))) - { - free(serial->Driver); - free(serial->Path); - free(serial->Name); - free(serial); - return FALSE; - } - } - - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*)serial)) - { - free(serial->Permissive); - free(serial->Driver); - free(serial->Path); - free(serial->Name); - free(serial); + freerdp_device_free(serial); return FALSE; } @@ -718,44 +635,22 @@ BOOL freerdp_client_add_device_channel(rdpSettings* settings, size_t count, cons } else if (strcmp(params[0], "parallel") == 0) { - RDPDR_PARALLEL* parallel; + RDPDR_DEVICE* parallel; if (count < 1) return FALSE; settings->RedirectParallelPorts = TRUE; settings->DeviceRedirection = TRUE; - parallel = (RDPDR_PARALLEL*)calloc(1, sizeof(RDPDR_PARALLEL)); + + parallel = freerdp_device_new(RDPDR_DTYP_PARALLEL, count - 1, ¶ms[1]); if (!parallel) return FALSE; - parallel->Type = RDPDR_DTYP_PARALLEL; - - if (count > 1) + if (!freerdp_device_collection_add(settings, parallel)) { - if (!(parallel->Name = _strdup(params[1]))) - { - free(parallel); - return FALSE; - } - } - - if (count > 2) - { - if (!(parallel->Path = _strdup(params[2]))) - { - free(parallel->Name); - free(parallel); - return FALSE; - } - } - - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*)parallel)) - { - free(parallel->Path); - free(parallel->Name); - free(parallel); + freerdp_device_free(parallel); return FALSE; } @@ -977,7 +872,11 @@ static int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_A { settings->PasswordIsSmartcardPin = enable; } - CommandLineSwitchEnd(arg) return status ? 1 : -1; + CommandLineSwitchEnd(arg) + + return status + ? 1 + : -1; } BOOL freerdp_parse_username(const char* username, char** user, char** domain) @@ -3715,37 +3614,35 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) if (settings->RedirectSmartCards) { - RDPDR_SMARTCARD* smartcard; - if (!freerdp_device_collection_find_type(settings, RDPDR_DTYP_SMARTCARD)) { - smartcard = (RDPDR_SMARTCARD*)calloc(1, sizeof(RDPDR_SMARTCARD)); + RDPDR_DEVICE* smartcard = freerdp_device_new(RDPDR_DTYP_SMARTCARD, 0, NULL); if (!smartcard) return FALSE; - smartcard->Type = RDPDR_DTYP_SMARTCARD; - - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*)smartcard)) + if (!freerdp_device_collection_add(settings, smartcard)) + { + freerdp_device_free(smartcard); return FALSE; + } } } if (settings->RedirectPrinters) { - RDPDR_PRINTER* printer; - if (!freerdp_device_collection_find_type(settings, RDPDR_DTYP_PRINT)) { - printer = (RDPDR_PRINTER*)calloc(1, sizeof(RDPDR_PRINTER)); + RDPDR_DEVICE* printer = freerdp_device_new(RDPDR_DTYP_PRINT, 0, NULL); if (!printer) return FALSE; - printer->Type = RDPDR_DTYP_PRINT; - - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*)printer)) + if (!freerdp_device_collection_add(settings, printer)) + { + freerdp_device_free(printer); return FALSE; + } } } diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 987dfa8ad..e5cd01375 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -452,9 +452,7 @@ typedef struct _RDPDR_DEVICE RDPDR_DEVICE; struct _RDPDR_DRIVE { - UINT32 Id; - UINT32 Type; - char* Name; + RDPDR_DEVICE device; char* Path; BOOL automount; }; @@ -462,26 +460,20 @@ typedef struct _RDPDR_DRIVE RDPDR_DRIVE; struct _RDPDR_PRINTER { - UINT32 Id; - UINT32 Type; - char* Name; + RDPDR_DEVICE device; char* DriverName; }; typedef struct _RDPDR_PRINTER RDPDR_PRINTER; struct _RDPDR_SMARTCARD { - UINT32 Id; - UINT32 Type; - char* Name; + RDPDR_DEVICE device; }; typedef struct _RDPDR_SMARTCARD RDPDR_SMARTCARD; struct _RDPDR_SERIAL { - UINT32 Id; - UINT32 Type; - char* Name; + RDPDR_DEVICE device; char* Path; char* Driver; char* Permissive; @@ -490,9 +482,7 @@ typedef struct _RDPDR_SERIAL RDPDR_SERIAL; struct _RDPDR_PARALLEL { - UINT32 Id; - UINT32 Type; - char* Name; + RDPDR_DEVICE device; char* Path; }; typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; @@ -1653,7 +1643,11 @@ extern "C" const char* name); FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 type); - FREERDP_API RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device); + + FREERDP_API RDPDR_DEVICE* freerdp_device_new(UINT32 Type, size_t count, const char* args[]); + FREERDP_API RDPDR_DEVICE* freerdp_device_clone(const RDPDR_DEVICE* device); + FREERDP_API void freerdp_device_free(RDPDR_DEVICE* device); + FREERDP_API void freerdp_device_collection_free(rdpSettings* settings); FREERDP_API BOOL freerdp_static_channel_collection_add(rdpSettings* settings, diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index da1f28968..b8bece925 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -208,15 +208,19 @@ int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, const char* previous, BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device) { - if (!settings->DeviceArray) - return FALSE; + UINT32 count; + WINPR_ASSERT(settings); + WINPR_ASSERT(device); - if (freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize) < - (settings->DeviceCount + 1)) + count = settings->DeviceCount + 1; + if (freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize) < count) { UINT32 new_size; RDPDR_DEVICE** new_array; new_size = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize) * 2; + if (new_size == 0) + new_size = count * 2; + new_array = (RDPDR_DEVICE**)realloc(settings->DeviceArray, new_size * sizeof(RDPDR_DEVICE*)); @@ -267,215 +271,267 @@ RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 return NULL; } -RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device) +RDPDR_DEVICE* freerdp_device_new(UINT32 Type, size_t count, const char* args[]) { - if (device->Type == RDPDR_DTYP_FILESYSTEM) + size_t size; + union { - RDPDR_DRIVE* drive = (RDPDR_DRIVE*)device; - RDPDR_DRIVE* _drive = (RDPDR_DRIVE*)calloc(1, sizeof(RDPDR_DRIVE)); + RDPDR_DEVICE* base; + RDPDR_DRIVE* drive; + RDPDR_SERIAL* serial; + RDPDR_PRINTER* printer; + RDPDR_PARALLEL* parallel; + RDPDR_SMARTCARD* smartcard; + } device; - if (!_drive) - return NULL; + device.base = NULL; + WINPR_ASSERT(args || (count == 0)); - _drive->Id = drive->Id; - _drive->Type = drive->Type; - _drive->Name = _strdup(drive->Name); - - if (!_drive->Name) - goto out_fs_name_error; - - _drive->Path = _strdup(drive->Path); - - if (!_drive->Path) - goto out_fs_path_error; - - return (RDPDR_DEVICE*)_drive; - out_fs_path_error: - free(_drive->Name); - out_fs_name_error: - free(_drive); - return NULL; + switch (Type) + { + case RDPDR_DTYP_PRINT: + size = sizeof(RDPDR_PRINTER); + break; + case RDPDR_DTYP_SERIAL: + size = sizeof(RDPDR_SERIAL); + break; + case RDPDR_DTYP_PARALLEL: + size = sizeof(RDPDR_PARALLEL); + break; + case RDPDR_DTYP_SMARTCARD: + size = sizeof(RDPDR_SMARTCARD); + break; + case RDPDR_DTYP_FILESYSTEM: + size = sizeof(RDPDR_DRIVE); + break; + default: + goto fail; } - if (device->Type == RDPDR_DTYP_PRINT) + device.base = calloc(1, size); + if (!device.base) + goto fail; + device.base->Id = 0; + device.base->Type = Type; + + if (count > 0) { - RDPDR_PRINTER* printer = (RDPDR_PRINTER*)device; - RDPDR_PRINTER* _printer = (RDPDR_PRINTER*)calloc(1, sizeof(RDPDR_PRINTER)); + device.base->Name = _strdup(args[1]); + if (!device.base->Name) + goto fail; - if (!_printer) - return NULL; - - _printer->Id = printer->Id; - _printer->Type = printer->Type; - - if (printer->Name) + switch (Type) { - _printer->Name = _strdup(printer->Name); + case RDPDR_DTYP_PRINT: + if (count > 1) + { + device.printer->DriverName = _strdup(args[1]); + if (!device.printer->DriverName) + goto fail; + } + break; + case RDPDR_DTYP_SERIAL: + if (count > 1) + { + device.serial->Path = _strdup(args[1]); + if (!device.serial->Path) + goto fail; + } - if (!_printer->Name) - goto out_print_name_error; + if (count > 2) + { + device.serial->Driver = _strdup(args[2]); + if (!device.serial->Driver) + goto fail; + } + + if (count > 3) + { + device.serial->Permissive = _strdup(args[1]); + if (!device.serial->Permissive) + goto fail; + } + size = sizeof(RDPDR_SERIAL); + break; + case RDPDR_DTYP_PARALLEL: + if (count > 1) + { + device.parallel->Path = _strdup(args[1]); + if (!device.serial->Path) + goto fail; + } + break; + case RDPDR_DTYP_SMARTCARD: + break; + case RDPDR_DTYP_FILESYSTEM: + if (count > 1) + { + device.drive->Path = _strdup(args[1]); + if (!device.drive->Path) + goto fail; + } + if (count > 2) + device.drive->automount = (args[2] == NULL) ? FALSE : TRUE; + break; + default: + goto fail; } + } + return device.base; - if (printer->DriverName) - { - _printer->DriverName = _strdup(printer->DriverName); +fail: + freerdp_device_free(device.base); + return NULL; +} - if (!_printer->DriverName) - goto out_print_path_error; - } +void freerdp_device_free(RDPDR_DEVICE* device) +{ + union + { + RDPDR_DEVICE* dev; + RDPDR_DRIVE* drive; + RDPDR_SERIAL* serial; + RDPDR_PRINTER* printer; + RDPDR_PARALLEL* parallel; + RDPDR_SMARTCARD* smartcard; + } cnv; - return (RDPDR_DEVICE*)_printer; - out_print_path_error: - free(_printer->Name); - out_print_name_error: - free(_printer); + cnv.dev = device; + if (!cnv.dev) + return; + + switch (device->Type) + { + case RDPDR_DTYP_PRINT: + free(cnv.printer->DriverName); + break; + case RDPDR_DTYP_SERIAL: + free(cnv.serial->Path); + free(cnv.serial->Driver); + free(cnv.serial->Permissive); + break; + case RDPDR_DTYP_PARALLEL: + free(cnv.parallel->Path); + break; + case RDPDR_DTYP_SMARTCARD: + break; + case RDPDR_DTYP_FILESYSTEM: + free(cnv.drive->Path); + break; + default: + break; + } + free(cnv.dev->Name); + free(cnv.dev); +} + +RDPDR_DEVICE* freerdp_device_clone(const RDPDR_DEVICE* device) +{ + union + { + const RDPDR_DEVICE* dev; + const RDPDR_DRIVE* drive; + const RDPDR_SERIAL* serial; + const RDPDR_PRINTER* printer; + const RDPDR_PARALLEL* parallel; + const RDPDR_SMARTCARD* smartcard; + } src; + + union + { + RDPDR_DEVICE* dev; + RDPDR_DRIVE* drive; + RDPDR_SERIAL* serial; + RDPDR_PRINTER* printer; + RDPDR_PARALLEL* parallel; + RDPDR_SMARTCARD* smartcard; + } copy; + + WINPR_ASSERT(device); + + src.dev = device; + copy.dev = freerdp_device_new(device->Id, device->Type, device->Name); + if (!copy.dev) return NULL; + + switch (device->Type) + { + case RDPDR_DTYP_FILESYSTEM: + { + if (src.drive->Path) + copy.drive->Path = _strdup(src.drive->Path); + + if (!copy.drive->Path) + goto fail; + } + break; + + case RDPDR_DTYP_PRINT: + { + if (copy.printer->DriverName) + { + copy.printer->DriverName = _strdup(src.printer->DriverName); + + if (!copy.printer->DriverName) + goto fail; + } + } + break; + + case RDPDR_DTYP_SMARTCARD: + break; + + case RDPDR_DTYP_SERIAL: + { + if (copy.serial->Path) + { + copy.serial->Path = _strdup(src.serial->Path); + + if (!copy.serial->Path) + goto fail; + } + + if (copy.serial->Driver) + { + copy.serial->Driver = _strdup(src.serial->Driver); + + if (!copy.serial->Driver) + goto fail; + } + } + break; + + case RDPDR_DTYP_PARALLEL: + { + if (src.parallel->Path) + copy.parallel->Path = _strdup(src.parallel->Path); + + if (!copy.parallel->Path) + goto fail; + } + break; + default: + WLog_ERR(TAG, "unknown device type %" PRIu32 "", device->Type); + break; } - if (device->Type == RDPDR_DTYP_SMARTCARD) - { - RDPDR_SMARTCARD* smartcard = (RDPDR_SMARTCARD*)device; - RDPDR_SMARTCARD* _smartcard = (RDPDR_SMARTCARD*)calloc(1, sizeof(RDPDR_SMARTCARD)); + return copy.dev; - if (!_smartcard) - return NULL; - - _smartcard->Id = smartcard->Id; - _smartcard->Type = smartcard->Type; - - if (smartcard->Name) - { - _smartcard->Name = _strdup(smartcard->Name); - - if (!_smartcard->Name) - goto out_smartc_name_error; - } - - return (RDPDR_DEVICE*)_smartcard; - out_smartc_name_error: - free(_smartcard); - return NULL; - } - - if (device->Type == RDPDR_DTYP_SERIAL) - { - RDPDR_SERIAL* serial = (RDPDR_SERIAL*)device; - RDPDR_SERIAL* _serial = (RDPDR_SERIAL*)calloc(1, sizeof(RDPDR_SERIAL)); - - if (!_serial) - return NULL; - - _serial->Id = serial->Id; - _serial->Type = serial->Type; - - if (serial->Name) - { - _serial->Name = _strdup(serial->Name); - - if (!_serial->Name) - goto out_serial_name_error; - } - - if (serial->Path) - { - _serial->Path = _strdup(serial->Path); - - if (!_serial->Path) - goto out_serial_path_error; - } - - if (serial->Driver) - { - _serial->Driver = _strdup(serial->Driver); - - if (!_serial->Driver) - goto out_serial_driver_error; - } - - return (RDPDR_DEVICE*)_serial; - out_serial_driver_error: - free(_serial->Path); - out_serial_path_error: - free(_serial->Name); - out_serial_name_error: - free(_serial); - return NULL; - } - - if (device->Type == RDPDR_DTYP_PARALLEL) - { - RDPDR_PARALLEL* parallel = (RDPDR_PARALLEL*)device; - RDPDR_PARALLEL* _parallel = (RDPDR_PARALLEL*)calloc(1, sizeof(RDPDR_PARALLEL)); - - if (!_parallel) - return NULL; - - _parallel->Id = parallel->Id; - _parallel->Type = parallel->Type; - - if (parallel->Name) - { - _parallel->Name = _strdup(parallel->Name); - - if (!_parallel->Name) - goto out_parallel_name_error; - } - - if (parallel->Path) - { - _parallel->Path = _strdup(parallel->Path); - - if (!_parallel->Path) - goto out_parallel_path_error; - } - - return (RDPDR_DEVICE*)_parallel; - out_parallel_path_error: - free(_parallel->Name); - out_parallel_name_error: - free(_parallel); - return NULL; - } - - WLog_ERR(TAG, "unknown device type %" PRIu32 "", device->Type); +fail: + freerdp_device_free(copy.dev); return NULL; } void freerdp_device_collection_free(rdpSettings* settings) { UINT32 index; - RDPDR_DEVICE* device; + + WINPR_ASSERT(settings); for (index = 0; index < settings->DeviceCount; index++) { - device = (RDPDR_DEVICE*)settings->DeviceArray[index]; - - if (!device) - continue; - - free(device->Name); - - if (settings->DeviceArray[index]->Type == RDPDR_DTYP_FILESYSTEM) - { - free(((RDPDR_DRIVE*)device)->Path); - } - else if (settings->DeviceArray[index]->Type == RDPDR_DTYP_PRINT) - { - } - else if (settings->DeviceArray[index]->Type == RDPDR_DTYP_SMARTCARD) - { - } - else if (settings->DeviceArray[index]->Type == RDPDR_DTYP_SERIAL) - { - free(((RDPDR_SERIAL*)device)->Path); - free(((RDPDR_SERIAL*)device)->Driver); - } - else if (settings->DeviceArray[index]->Type == RDPDR_DTYP_PARALLEL) - { - free(((RDPDR_PARALLEL*)device)->Path); - } - - free(device); + RDPDR_DEVICE* device = (RDPDR_DEVICE*)settings->DeviceArray[index]; + freerdp_device_free(device); } free(settings->DeviceArray); @@ -511,15 +567,19 @@ BOOL freerdp_static_channel_collection_del(rdpSettings* settings, const char* na BOOL freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel) { UINT32 count; - if (!settings->StaticChannelArray) - return FALSE; - if (freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize) < - (freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount) + 1)) + WINPR_ASSERT(settings); + WINPR_ASSERT(channel); + + count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount) + 1; + if (freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize) < count) { UINT32 new_size; ADDIN_ARGV** new_array; new_size = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize) * 2; + if (new_size == 0) + new_size = count * 2; + new_array = (ADDIN_ARGV**)realloc(settings->StaticChannelArray, new_size * sizeof(ADDIN_ARGV*)); @@ -541,6 +601,9 @@ ADDIN_ARGV* freerdp_static_channel_collection_find(rdpSettings* settings, const UINT32 index; ADDIN_ARGV* channel; + WINPR_ASSERT(settings); + WINPR_ASSERT(name); + for (index = 0; index < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount); index++) { @@ -557,6 +620,9 @@ void freerdp_static_channel_collection_free(rdpSettings* settings) { UINT32 i; + if (!settings) + return; + for (i = 0; i < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount); i++) { freerdp_addin_argv_free(settings->StaticChannelArray[i]); @@ -597,15 +663,18 @@ BOOL freerdp_dynamic_channel_collection_del(rdpSettings* settings, const char* n BOOL freerdp_dynamic_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel) { UINT32 count; - if (!settings->DynamicChannelArray) - return FALSE; - if (freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize) < - (freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount) + 1)) + WINPR_ASSERT(settings); + WINPR_ASSERT(channel); + + count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount) + 1; + if (freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize) < count) { ADDIN_ARGV** new_array; - const size_t size = - freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize) * 2; + size_t size = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize) * 2; + if (size == 0) + size = count * 2; + new_array = realloc(settings->DynamicChannelArray, sizeof(ADDIN_ARGV*) * size); if (!new_array) @@ -626,6 +695,9 @@ ADDIN_ARGV* freerdp_dynamic_channel_collection_find(const rdpSettings* settings, UINT32 index; ADDIN_ARGV* channel; + WINPR_ASSERT(settings); + WINPR_ASSERT(name); + for (index = 0; index < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount); index++) { diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index f0f512158..e375bd15f 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -584,28 +584,6 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!settings->ClientTimeZone) goto out_fail; - freerdp_settings_set_uint32(settings, FreeRDP_DeviceArraySize, 16); - settings->DeviceArray = (RDPDR_DEVICE**)calloc( - freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize), sizeof(RDPDR_DEVICE*)); - - if (!settings->DeviceArray) - goto out_fail; - - freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize, 16); - settings->StaticChannelArray = (ADDIN_ARGV**)calloc( - freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize), sizeof(ADDIN_ARGV*)); - - if (!settings->StaticChannelArray) - goto out_fail; - - freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize, 16); - settings->DynamicChannelArray = - (ADDIN_ARGV**)calloc(freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize), - sizeof(ADDIN_ARGV*)); - - if (!settings->DynamicChannelArray) - goto out_fail; - if (!freerdp_settings_set_bool(settings, FreeRDP_TcpKeepAlive, TRUE) || !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveRetries, 3) || !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveDelay, 5) ||