Cygwin: use locale-aware conversion to UNICODE_STRING checking mount points

mount_info::get_mounts_here used RtlCreateUnicodeStringFromAsciiz
which translates bytes into wide chars verbatim.

Create a new function sys_mbstouni_alloc which can be used from
mount_info::get_mounts_here to convert multibyte mount point
strings to UNICODE_STRINGS in a locale-aware way.

For symmetry, create a function mount_info::free_mounts_here,
so the knwoledge how to free the UNICODE_STRING buffers is
encapsulated in the same class.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2022-08-04 23:48:19 +02:00
parent 35c5017438
commit 58e981a5a4
4 changed files with 35 additions and 16 deletions

View File

@ -40,7 +40,7 @@ class __DIR_mounts
{
int count;
const char *parent_dir;
int parent_dir_len;
size_t parent_dir_len;
UNICODE_STRING mounts[MAX_MOUNTS];
bool found[MAX_MOUNTS + 3];
UNICODE_STRING cygdrive;
@ -60,9 +60,7 @@ public:
}
~__DIR_mounts ()
{
for (int i = 0; i < count; ++i)
RtlFreeUnicodeString (&mounts[i]);
RtlFreeUnicodeString (&cygdrive);
mount_table->free_mounts_here (mounts, count, &cygdrive);
}
/* For an entry within this dir, check if a mount point exists. */
bool check_mount (PUNICODE_STRING fname)

View File

@ -723,12 +723,12 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
return rc;
}
int
mount_info::get_mounts_here (const char *parent_dir, int parent_dir_len,
size_t
mount_info::get_mounts_here (const char *parent_dir, size_t parent_dir_len,
PUNICODE_STRING mount_points,
PUNICODE_STRING cygd)
{
int n_mounts = 0;
size_t n_mounts = 0;
for (int i = 0; i < nmounts; i++)
{
@ -739,20 +739,29 @@ mount_info::get_mounts_here (const char *parent_dir, int parent_dir_len,
if (last_slash == mi->posix_path)
{
if (parent_dir_len == 1 && mi->posix_pathlen > 1)
RtlCreateUnicodeStringFromAsciiz (&mount_points[n_mounts++],
last_slash + 1);
sys_mbstouni_alloc (&mount_points[n_mounts++], HEAP_NOTHEAP,
last_slash + 1);
}
else if (parent_dir_len == last_slash - mi->posix_path
else if (parent_dir_len == (size_t) (last_slash - mi->posix_path)
&& strncasematch (parent_dir, mi->posix_path, parent_dir_len))
RtlCreateUnicodeStringFromAsciiz (&mount_points[n_mounts++],
last_slash + 1);
sys_mbstouni_alloc (&mount_points[n_mounts++], HEAP_NOTHEAP,
last_slash + 1);
}
RtlCreateUnicodeStringFromAsciiz (cygd, cygdrive + 1);
sys_mbstouni_alloc (cygd, HEAP_NOTHEAP, cygdrive + 1);
if (cygd->Length)
cygd->Length -= 2; // Strip trailing slash
return n_mounts;
}
void
mount_info::free_mounts_here (PUNICODE_STRING mount_points, int n_mounts,
PUNICODE_STRING cygd)
{
for (int i = 0; i < n_mounts; ++i)
free (mount_points[i].Buffer);
free (cygd->Buffer);
}
/* cygdrive_posix_path: Build POSIX path used as the
mount point for cygdrives created when there is no other way to
obtain a POSIX path from a Win32 one.

View File

@ -199,9 +199,11 @@ class mount_info
int get_cygdrive_info (char *user, char *system, char* user_flags,
char* system_flags);
void cygdrive_posix_path (const char *src, char *dst, int flags);
int get_mounts_here (const char *parent_dir, int,
PUNICODE_STRING mount_points,
PUNICODE_STRING cygd);
size_t get_mounts_here (const char *parent_dir, size_t,
PUNICODE_STRING mount_points,
PUNICODE_STRING cygd);
void free_mounts_here (PUNICODE_STRING, int, PUNICODE_STRING);
private:
void sort ();

View File

@ -91,6 +91,16 @@ sys_mbstowcs (wchar_t * dst, size_t dlen, const char *src,
size_t sys_mbstowcs_alloc (wchar_t **, int, const char *, size_t = (size_t) -1);
static inline size_t
sys_mbstouni_alloc (PUNICODE_STRING dst, int type, const char *src,
size_t nms = (size_t) -1)
{
size_t len = sys_mbstowcs_alloc (&dst->Buffer, type, src, nms);
dst->MaximumLength = len * sizeof (WCHAR);
dst->Length = dst->MaximumLength - sizeof (WCHAR);
return dst->MaximumLength;
}
#endif /* __cplusplus */
#endif /* __INSIDE_CYGWIN__ */