Unified DriveStoreRedirect parsing.

This commit is contained in:
Armin Novak 2019-08-23 11:47:31 +02:00
parent d8bf05367b
commit fdf1715213
3 changed files with 159 additions and 182 deletions

View File

@ -884,6 +884,12 @@ static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
DRIVE_DEVICE* drive;
UINT error;
if (!pEntryPoints || !name || !path)
{
WLog_ERR(TAG, "[%s] Invalid parameters: pEntryPoints=%p, name=%p, path=%p", pEntryPoints, name, path);
return ERROR_INVALID_PARAMETER;
}
if (name[0] && path[0])
{
size_t pathLength = strnlen(path, MAX_PATH);

View File

@ -48,6 +48,83 @@
#include <freerdp/log.h>
#define TAG CLIENT_TAG("common.cmdline")
static BOOL freerdp_path_valid(const char* path, BOOL* special)
{
const char DynamicDrives[] = "DynamicDrives";
BOOL isPath = FALSE;
BOOL isSpecial;
if (!path)
return FALSE;
isSpecial = (strncmp(path, "*", 2) == 0) ||
(strncmp(path, DynamicDrives, sizeof(DynamicDrives)) == 0) ||
(strncmp(path, "%", 2) == 0) ? TRUE : FALSE;
if (!isSpecial)
isPath = PathFileExistsA(path);
if (special)
*special = isSpecial;
return isSpecial || isPath;
}
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;
if (name)
{
/* Path was entered as secondary argument, swap */
if (PathFileExistsA(name))
{
const char* tmp = path;
path = name;
name = tmp;
}
}
if (name)
{
if (!(drive->Name = _strdup(name)))
goto fail;
}
else /* We need a name to send to the server. */
if (!(drive->Name = _strdup(path)))
goto fail;
if (!path)
goto fail;
else
{
BOOL isSpecial = FALSE;
BOOL isPath = freerdp_path_valid(path, &isSpecial);
if (isSpecial && name)
goto fail;
if ((!isPath && !isSpecial) || !(drive->Path = _strdup(path)))
goto fail;
}
if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) drive))
goto fail;
return TRUE;
fail:
free(drive->Path);
free(drive->Name);
free(drive);
return FALSE;
}
static BOOL copy_value(const char* value, char** dst)
{
if (!dst || !value)
@ -335,53 +412,17 @@ BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count,
{
if (strcmp(params[0], "drive") == 0)
{
RDPDR_DRIVE* drive;
if (count < 3)
BOOL rc;
if (count < 2)
return FALSE;
settings->DeviceRedirection = TRUE;
drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE));
if (count < 3)
rc = freerdp_client_add_drive(settings, params[1], NULL);
else
rc = freerdp_client_add_drive(settings, params[2], params[1]);
if (!drive)
return FALSE;
drive->Type = RDPDR_DTYP_FILESYSTEM;
if (count > 1)
{
if (!(drive->Name = _strdup(params[1])))
{
free(drive);
return FALSE;
}
}
if (count > 2)
{
const char DynamicDrives[] = "DynamicDrives";
const BOOL isPath = PathFileExistsA(params[2]);
const BOOL isSpecial = (strncmp(params[2], "*", 2) == 0) ||
(strncmp(params[2], DynamicDrives, sizeof(DynamicDrives)) == 0) ||
(strncmp(params[2], "%", 2) == 0) ? TRUE : FALSE;
if ((!isPath && !isSpecial) || !(drive->Path = _strdup(params[2])))
{
free(drive->Name);
free(drive);
return FALSE;
}
}
if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) drive))
{
free(drive->Path);
free(drive->Name);
free(drive);
return FALSE;
}
return TRUE;
return rc;
}
else if (strcmp(params[0], "printer") == 0)
{
@ -3175,6 +3216,72 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
TRUE; /* these RDP8 features require rdpdr to be registered */
}
if (settings->DrivesToRedirect && (strlen(settings->DrivesToRedirect) != 0))
{
/*
* Drives to redirect:
*
* Very similar to DevicesToRedirect, but can contain a
* comma-separated list of drive letters to redirect.
*/
char* value;
char* tok;
char* context = NULL;
value = _strdup(settings->DrivesToRedirect);
if (!value)
return FALSE;
tok = strtok_s(value, ";", &context);
if (!tok)
{
free(value);
return FALSE;
}
while(tok)
{
/* Syntax: Comma seperated list of the following entries:
* '*' ... Redirect all drives, including hotplug
* 'DynamicDrives' ... hotplug
* <label>(<path>) ... One or more paths to redirect.
* <path>(<label>) ... One or more paths to redirect.
* <path> ... One or more paths to redirect.
*/
/* TODO: Need to properly escape labels and paths */
BOOL success;
const char* name = NULL;
const char* drive = tok;
char* start = strtok(tok, "(");
char* end = strtok(NULL, ")");
if (end)
name = end;
if (freerdp_path_valid(name, NULL) && freerdp_path_valid(drive, NULL))
{
success = freerdp_client_add_drive(settings, name, NULL);
if (success)
success = freerdp_client_add_drive(settings, drive, NULL);
}
else
success = freerdp_client_add_drive(settings, drive, name);
if (!success)
{
free(value);
return FALSE;
}
tok = strtok_s(NULL, ";", &context);
}
free(value);
if (!freerdp_settings_set_bool(settings, FreeRDP_DeviceRedirection, TRUE))
return FALSE;
settings->DeviceRedirection = TRUE;
}
if (settings->RedirectDrives || settings->RedirectHomeDrive
|| settings->RedirectSerialPorts
|| settings->RedirectSmartCards || settings->RedirectPrinters)

View File

@ -51,7 +51,6 @@
/*#define DEBUG_CLIENT_FILE 1*/
static const BYTE BOM_UTF16_LE[2] = { 0xFF, 0xFE };
static const char DynamicDrives[] = "DynamicDrives";
#define INVALID_INTEGER_VALUE 0xFFFFFFFF
@ -786,6 +785,7 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett
SETTING_MODIFIED_SET_STRING(file->AlternateShell, settings, AlternateShell);
SETTING_MODIFIED_SET_STRING(file->ShellWorkingDirectory, settings, ShellWorkingDirectory);
SETTING_MODIFIED_SET(file->ConnectionType, settings, ConnectionType);
SETTING_MODIFIED_SET_STRING(file->DrivesToRedirect, settings, DrivesToRedirect);
if (SETTING_MODIFIED(settings, AudioPlayback) || SETTING_MODIFIED(settings, RemoteConsoleAudio))
{
@ -1047,79 +1047,6 @@ size_t freerdp_client_write_rdp_file_buffer(const rdpFile* file, char* buffer, s
return totalSize;
}
static BOOL freerdp_path_valid(const char* path, BOOL* special)
{
BOOL isPath = FALSE;
BOOL isSpecial;
if (!path)
return FALSE;
isSpecial = (strncmp(path, "*", 2) == 0) ||
(strncmp(path, DynamicDrives, sizeof(DynamicDrives)) == 0) ||
(strncmp(path, "%", 2) == 0) ? TRUE : FALSE;
if (!isSpecial)
isPath = PathFileExistsA(path);
if (special)
*special = isSpecial;
return isSpecial || isPath;
}
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;
if (name)
{
/* Path was entered as secondary argument, swap */
if (PathFileExistsA(name))
{
const char* tmp = path;
path = name;
name = tmp;
}
}
if (name)
{
if (!(drive->Name = _strdup(name)))
goto fail;
}
if (!path)
goto fail;
else
{
BOOL isSpecial = FALSE;
BOOL isPath = freerdp_path_valid(path, &isSpecial);
if (isSpecial && name)
goto fail;
if ((!isPath && !isSpecial) || !(drive->Path = _strdup(path)))
goto fail;
}
if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) drive))
goto fail;
return TRUE;
fail:
free(drive->Path);
free(drive->Name);
free(drive);
return FALSE;
}
BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings)
{
if (~((size_t)file->Domain))
@ -1623,71 +1550,8 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
if (~((size_t)file->DrivesToRedirect))
{
/*
* Drives to redirect:
*
* Very similar to DevicesToRedirect, but can contain a
* comma-separated list of drive letters to redirect.
*/
const BOOL empty = !file->DrivesToRedirect || (strlen(file->DrivesToRedirect) == 0);
if (!empty)
{
char* value;
char* tok;
char* context = NULL;
value = _strdup(file->DrivesToRedirect);
if (!value)
return FALSE;
tok = strtok_s(value, ";", &context);
if (!tok)
{
free(value);
return FALSE;
}
while(tok)
{
/* Syntax: Comma seperated list of the following entries:
* '*' ... Redirect all drives, including hotplug
* 'DynamicDrives' ... hotplug
* <label>(<path>) ... One or more paths to redirect.
* <path>(<label>) ... One or more paths to redirect.
* <path> ... One or more paths to redirect.
*/
/* TODO: Need to properly escape labels and paths */
BOOL success;
const char* name = NULL;
const char* drive = tok;
char* start = strtok(tok, "(");
char* end = strtok(NULL, ")");
if (end)
name = end;
if (freerdp_path_valid(name, NULL) && freerdp_path_valid(drive, NULL))
{
success = freerdp_client_add_drive(settings, name, NULL);
if (success)
success = freerdp_client_add_drive(settings, drive, NULL);
}
else
success = freerdp_client_add_drive(settings, drive, name);
if (!success)
{
free(value);
return FALSE;
}
tok = strtok_s(NULL, ";", &context);
}
free(value);
if (!freerdp_settings_set_bool(settings, FreeRDP_DeviceRedirection, TRUE))
return FALSE;
}
if (!freerdp_settings_set_string(settings, FreeRDP_DrivesToRedirect, file->DrivesToRedirect))
return FALSE;
}
if (~file->KeyboardHook)