Update drive redirection code to use new UTF-8 calls

This commit is contained in:
matt335672 2023-10-16 13:44:46 +01:00
parent f8e7fd4c2c
commit 8556f83905

View File

@ -141,8 +141,6 @@ static int devredir_proc_query_dir_response(IRP *irp,
enum NTSTATUS IoStatus);
static void devredir_cvt_slash(char *path);
static void devredir_cvt_to_unicode(char *unicode, const char *path);
static void devredir_cvt_from_unicode_len(char *path, char *unicode, int len);
static int devredir_string_ends_with(const char *string, char c);
/*****************************************************************************/
@ -571,9 +569,12 @@ devredir_send_server_device_announce_resp(tui32 device_id,
}
/**
* Create a file system object
*
* See [MS-RDPEFS] 2.2.1.4.1 (DR_CREATE_REQ)
*
* @return 0 on success, -1 on failure
*****************************************************************************/
static int
devredir_send_drive_create_request(tui32 device_id,
const char *path,
@ -585,7 +586,8 @@ devredir_send_drive_create_request(tui32 device_id,
{
struct stream *s;
int bytes;
int len;
int path_len;
unsigned int unicode_byte_count;
tui32 SharedAccess;
LOG_DEVEL(LOG_LEVEL_DEBUG, "device_id=%d path=\"%s\""
@ -597,10 +599,11 @@ devredir_send_drive_create_request(tui32 device_id,
FileAttributes, CreateOptions,
completion_id);
/* path in unicode needs this much space */
len = ((g_mbstowcs(NULL, path, 0) * sizeof(twchar)) / 2) + 2;
/* Find number of bytes required for Unicode path + terminator */
path_len = strlen(path) + 1; // includes terminator
unicode_byte_count = utf8_as_utf16_word_count(path, path_len) * 2;
xstream_new(s, 1024 + len);
xstream_new(s, (int)(64 + unicode_byte_count));
/* FILE_SHARE_DELETE allows files to be renamed while in use
(in some circumstances) */
@ -621,9 +624,8 @@ devredir_send_drive_create_request(tui32 device_id,
xstream_wr_u32_le(s, SharedAccess); /* SharedAccess */
xstream_wr_u32_le(s, CreateDisposition); /* CreateDisposition */
xstream_wr_u32_le(s, CreateOptions); /* CreateOptions */
xstream_wr_u32_le(s, len); /* PathLength */
devredir_cvt_to_unicode(s->p, path); /* path in unicode */
xstream_seek(s, len);
xstream_wr_u32_le(s, unicode_byte_count);/* PathLength */
out_utf8_as_utf16_le(s, path, path_len); /* Path */
/* send to client */
bytes = xstream_len(s);
@ -671,34 +673,31 @@ devredir_send_drive_close_request(tui16 Component, tui16 PacketId,
/**
* @brief ask client to enumerate directory
*
* Server Drive Query Directory Request
* DR_DRIVE_QUERY_DIRECTORY_REQ
*
* See [MS-RDPEFS] 2.2.3.3.10 (DR_DRIVE_QUERY_DIRECTORY_REQ)
*****************************************************************************/
// LK_TODO Path needs to be Unicode
static void
devredir_send_drive_dir_request(IRP *irp, tui32 device_id,
tui32 InitialQuery, char *Path)
{
struct stream *s;
int bytes;
char upath[4096]; // LK_TODO need to malloc this
int path_len = 0;
unsigned int path_len;
unsigned int unicode_byte_count;
/* during Initial Query, Path cannot be NULL */
if (InitialQuery)
if (InitialQuery && Path != NULL)
{
if (Path == NULL)
{
return;
}
/* Path in unicode needs this much space */
path_len = ((g_mbstowcs(NULL, Path, 0) * sizeof(twchar)) / 2) + 2;
devredir_cvt_to_unicode(upath, Path);
/* Find number of words required for Unicode path */
path_len = strlen(Path) + 1; // includes terminator
unicode_byte_count = utf8_as_utf16_word_count(Path, path_len) * 2;
}
else
{
path_len = 0;
unicode_byte_count = 0;
}
xstream_new(s, 1024 + path_len);
xstream_new(s, (int)(64 + unicode_byte_count));
irp->completion_type = CID_DIRECTORY_CONTROL;
devredir_insert_DeviceIoRequest(s,
@ -711,17 +710,9 @@ devredir_send_drive_dir_request(IRP *irp, tui32 device_id,
xstream_wr_u32_le(s, FileDirectoryInformation); /* FsInformationClass */
xstream_wr_u8(s, InitialQuery); /* InitialQuery */
if (!InitialQuery)
{
xstream_wr_u32_le(s, 0); /* PathLength */
xstream_seek(s, 23);
}
else
{
xstream_wr_u32_le(s, path_len); /* PathLength */
xstream_seek(s, 23); /* Padding */
xstream_wr_string(s, upath, path_len);
}
xstream_wr_u32_le(s, unicode_byte_count); /* PathLength */
xstream_seek(s, 23); /* Padding */
out_utf8_as_utf16_le(s, Path, path_len); /* Path */
/* send to client */
bytes = xstream_len(s);
@ -1191,6 +1182,7 @@ devredir_proc_query_dir_response(IRP *irp,
tui32 FileAttributes;
tui32 FileNameLength;
struct file_attr fattr;
unsigned int flen;
xstream_rd_u32_le(s_in, NextEntryOffset);
xstream_seek(s_in, 4); /* FileIndex */
@ -1208,8 +1200,14 @@ devredir_proc_query_dir_response(IRP *irp,
{
return -1;
}
devredir_cvt_from_unicode_len(filename, s_in->p, FileNameLength);
flen = in_utf16_le_fixed_as_utf8(s_in, FileNameLength / 2,
filename, sizeof(filename));
if (flen > sizeof(filename))
{
LOG(LOG_LEVEL_WARNING,
"Buffer was %d bytes too small for filename",
(int)(flen - sizeof(filename)));
}
//LOG_DEVEL(LOG_LEVEL_DEBUG, "LastAccessTime: 0x%llx", LastAccessTime);
//LOG_DEVEL(LOG_LEVEL_DEBUG, "LastWriteTime: 0x%llx", LastWriteTime);
@ -1876,69 +1874,6 @@ devredir_cvt_slash(char *path)
}
}
static void
devredir_cvt_to_unicode(char *unicode, const char *path)
{
char *dest;
char *src;
int rv;
int i;
rv = g_mbstowcs((twchar *) unicode, path, strlen(path));
/* unicode is typically 4 bytes, but microsoft only uses 2 bytes */
src = unicode + sizeof(twchar); /* skip 1st unicode char */
dest = unicode + 2; /* first char already in place */
for (i = 1; i < rv; i++)
{
*dest++ = *src++;
*dest++ = *src++;
src += 2;
}
*dest++ = 0;
*dest++ = 0;
}
static void
devredir_cvt_from_unicode_len(char *path, char *unicode, int len)
{
char *dest;
char *dest_saved;
char *src;
int i;
int bytes_to_alloc;
int max_bytes;
bytes_to_alloc = (((len / 2) * sizeof(twchar)) + sizeof(twchar));
src = unicode;
dest = g_new0(char, bytes_to_alloc);
dest_saved = dest;
for (i = 0; i < len; i += 2)
{
*dest++ = *src++;
*dest++ = *src++;
dest += 2;
}
*dest++ = 0;
*dest++ = 0;
*dest++ = 0;
*dest++ = 0;
max_bytes = wcstombs(NULL, (wchar_t *) dest_saved, 0);
if (max_bytes > 0)
{
wcstombs(path, (wchar_t *) dest_saved, max_bytes);
path[max_bytes] = 0;
}
g_free(dest_saved);
}
static int
devredir_string_ends_with(const char *string, char c)
{
@ -2002,13 +1937,21 @@ devredir_proc_cid_rmdir_or_file_resp(IRP *irp, enum NTSTATUS IoStatus)
IRP_MJ_CLOSE, IRP_MN_NONE, 32);
}
/**
* Rename a file on response to the create drive request
*
* See :-
* - [MS-RDPEFS] 2.2.3.3.9 (DR_DRIVE_SET_INFORMATION_REQ)`
* - [MS-RDPEFS] 2.2.3.3.9.1 (RDP_FILE_RENAME_INFORMATION)
*****************************************************************************/
static void
devredir_proc_cid_rename_file(IRP *irp, enum NTSTATUS IoStatus)
{
struct stream *s;
int bytes;
int sblen; /* SetBuffer length */
int flen; /* FileNameLength */
unsigned int flen; /* FileNameLength */
unsigned int unicode_byte_count; /* Bytes to represent new name in UTF-16 */
unsigned int sblen; /* SetBuffer length */
if (IoStatus != STATUS_SUCCESS)
@ -2021,12 +1964,13 @@ devredir_proc_cid_rename_file(IRP *irp, enum NTSTATUS IoStatus)
return;
}
/* Path in unicode needs this much space */
flen = ((g_mbstowcs(NULL, irp->gen.rename.new_name, 0)
* sizeof(twchar)) / 2) + 2;
sblen = 6 + flen;
/* Find number of words required for Unicode path */
flen = strlen(irp->gen.rename.new_name) + 1; // includes terminator
unicode_byte_count = utf8_as_utf16_word_count(irp->gen.rename.new_name, flen) * 2;
/* Length of RDP_FILE_RENAME_INFORMATION struct */
sblen = (1 + 1 + 4) + unicode_byte_count;
xstream_new(s, 1024 + flen);
xstream_new(s, (int)(64 + unicode_byte_count));
irp->completion_type = CID_RENAME_FILE_RESP;
devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
@ -2038,11 +1982,9 @@ devredir_proc_cid_rename_file(IRP *irp, enum NTSTATUS IoStatus)
xstream_seek(s, 24); /* padding */
xstream_wr_u8(s, 1); /* ReplaceIfExists */
xstream_wr_u8(s, 0); /* RootDirectory */
xstream_wr_u32_le(s, flen); /* FileNameLength */
/* filename in unicode */
devredir_cvt_to_unicode(s->p, irp->gen.rename.new_name); /* UNICODE_TODO */
xstream_seek(s, flen);
xstream_wr_u32_le(s, unicode_byte_count); /* FileNameLength */
/* filename in Unicode */
out_utf8_as_utf16_le(s, irp->gen.rename.new_name, flen);
/* send to client */
bytes = xstream_len(s);