* fhandler_process.cc (dos_drive_mappings): Partially rewrite to
handle volumes mounted into juntion points correctly.
This commit is contained in:
parent
1e10d23a56
commit
01ba99e8cd
@ -1,3 +1,8 @@
|
||||
2011-12-12 Corinna Vinschen <vinschen@redhat.com>
|
||||
|
||||
* fhandler_process.cc (dos_drive_mappings): Partially rewrite to
|
||||
handle volumes mounted into juntion points correctly.
|
||||
|
||||
2011-12-12 Corinna Vinschen <vinschen@redhat.com>
|
||||
|
||||
* fhandler_process.cc (dos_drive_mappings::dos_drive_mappings): Fully
|
||||
|
@ -549,84 +549,88 @@ struct dos_drive_mappings
|
||||
struct mapping
|
||||
{
|
||||
mapping *next;
|
||||
int len;
|
||||
wchar_t drive_letter;
|
||||
wchar_t mapping[1];
|
||||
size_t doslen;
|
||||
size_t ntlen;
|
||||
wchar_t *dospath;
|
||||
wchar_t *ntdevpath;
|
||||
};
|
||||
mapping *mappings;
|
||||
|
||||
dos_drive_mappings ()
|
||||
: mappings(0)
|
||||
{
|
||||
/* The logical drive strings buffer holds a list of (at most 26)
|
||||
drive names separated by nulls and terminated by a double-null:
|
||||
tmp_pathbuf tp;
|
||||
wchar_t vol[64]; /* Long enough for Volume GUID string */
|
||||
wchar_t *devpath = tp.w_get ();
|
||||
wchar_t *mounts = tp.w_get ();
|
||||
|
||||
"a:\\\0b:\\\0...z:\\\0"
|
||||
|
||||
The annoying part is, QueryDosDeviceW wants only "x:" rather
|
||||
than the "x:\" we get back from GetLogicalDriveStringsW, so
|
||||
we'll have to strip out the trailing slash for each mapping.
|
||||
|
||||
The returned mapping a native NT pathname (\Device\...) which
|
||||
we can use to fix up the output of GetMappedFileNameW
|
||||
*/
|
||||
static unsigned const DBUFLEN = 26 * 4;
|
||||
wchar_t dbuf[DBUFLEN + 1];
|
||||
wchar_t pbuf[NT_MAX_PATH];
|
||||
wchar_t drive[] = {L'x', L':', 0};
|
||||
unsigned result = GetLogicalDriveStringsW (DBUFLEN * sizeof (wchar_t),
|
||||
dbuf);
|
||||
if (!result)
|
||||
debug_printf ("Failed to get logical DOS drive names: %lu",
|
||||
GetLastError ());
|
||||
else if (result > DBUFLEN)
|
||||
debug_printf ("Too many mapped drive letters: %u", result);
|
||||
/* Iterate over all volumes, fetch the first path from the list of
|
||||
DOS paths the volume is mounted to, or use the GUID volume path
|
||||
otherwise. */
|
||||
HANDLE sh = FindFirstVolumeW (vol, 64);
|
||||
if (sh == INVALID_HANDLE_VALUE)
|
||||
debug_printf ("FindFirstVolumeW, %E");
|
||||
else
|
||||
for (wchar_t *cur = dbuf; (*drive = *cur); cur = wcschr (cur, L'\0')+1)
|
||||
if (QueryDosDeviceW (drive, pbuf, NT_MAX_PATH))
|
||||
{
|
||||
/* The DOS drive mapping can be another symbolic link. The result
|
||||
is that the mapping won't work since the section name is the
|
||||
name after resolving all symbolic links. So we have to resolve
|
||||
symbolic links here, too. */
|
||||
for (int syml_cnt = 0; syml_cnt < SYMLOOP_MAX; ++syml_cnt)
|
||||
{
|
||||
UNICODE_STRING upath;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
NTSTATUS status;
|
||||
HANDLE h;
|
||||
do
|
||||
{
|
||||
DWORD len;
|
||||
/* Skip drives which are not mounted. */
|
||||
if (!GetVolumePathNamesForVolumeNameW (vol, mounts, NT_MAX_PATH, &len)
|
||||
|| mounts[0] == L'\0')
|
||||
continue;
|
||||
*wcsrchr (vol, L'\\') = L'\0';
|
||||
if (QueryDosDeviceW (vol + 4, devpath, NT_MAX_PATH))
|
||||
{
|
||||
/* The DOS drive mapping can be another symbolic link. If so,
|
||||
the mapping won't work since the section name is the name
|
||||
after resolving all symlinks. Resolve symlinks here, too. */
|
||||
for (int syml_cnt = 0; syml_cnt < SYMLOOP_MAX; ++syml_cnt)
|
||||
{
|
||||
UNICODE_STRING upath;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
NTSTATUS status;
|
||||
HANDLE h;
|
||||
|
||||
RtlInitUnicodeString (&upath, pbuf);
|
||||
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
|
||||
NULL, NULL);
|
||||
status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY,
|
||||
&attr);
|
||||
if (!NT_SUCCESS (status))
|
||||
break;
|
||||
RtlInitEmptyUnicodeString (&upath, pbuf,
|
||||
(NT_MAX_PATH - 1) * sizeof (WCHAR));
|
||||
status = NtQuerySymbolicLinkObject (h, &upath, NULL);
|
||||
NtClose (h);
|
||||
if (!NT_SUCCESS (status))
|
||||
break;
|
||||
pbuf[upath.Length / sizeof (WCHAR)] = L'\0';
|
||||
}
|
||||
size_t plen = wcslen (pbuf);
|
||||
size_t psize = plen * sizeof (wchar_t);
|
||||
debug_printf ("DOS drive %ls maps to %ls", drive, pbuf);
|
||||
mapping *m = (mapping*) malloc (sizeof (mapping) + psize);
|
||||
if (m)
|
||||
{
|
||||
m->next = mappings;
|
||||
m->len = plen;
|
||||
m->drive_letter = *drive;
|
||||
memcpy (m->mapping, pbuf, psize + sizeof (wchar_t));
|
||||
mappings = m;
|
||||
}
|
||||
}
|
||||
else
|
||||
debug_printf ("Unable to determine the native mapping for %ls "
|
||||
"(error %lu)", drive, GetLastError ());
|
||||
RtlInitUnicodeString (&upath, devpath);
|
||||
InitializeObjectAttributes (&attr, &upath,
|
||||
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY,
|
||||
&attr);
|
||||
if (!NT_SUCCESS (status))
|
||||
break;
|
||||
RtlInitEmptyUnicodeString (&upath, devpath, (NT_MAX_PATH - 1)
|
||||
* sizeof (WCHAR));
|
||||
status = NtQuerySymbolicLinkObject (h, &upath, NULL);
|
||||
NtClose (h);
|
||||
if (!NT_SUCCESS (status))
|
||||
break;
|
||||
devpath[upath.Length / sizeof (WCHAR)] = L'\0';
|
||||
}
|
||||
mapping *m = new mapping ();
|
||||
if (m)
|
||||
{
|
||||
m->dospath = wcsdup (mounts);
|
||||
m->ntdevpath = wcsdup (devpath);
|
||||
if (!m->dospath || !m->ntdevpath)
|
||||
{
|
||||
free (m->dospath);
|
||||
free (m->ntdevpath);
|
||||
delete m;
|
||||
continue;
|
||||
}
|
||||
m->doslen = wcslen (m->dospath);
|
||||
m->dospath[--m->doslen] = L'\0'; /* Drop trailing backslash */
|
||||
m->ntlen = wcslen (m->ntdevpath);
|
||||
m->next = mappings;
|
||||
mappings = m;
|
||||
}
|
||||
}
|
||||
else
|
||||
debug_printf ("Unable to determine the native mapping for %ls "
|
||||
"(error %lu)", vol, GetLastError ());
|
||||
}
|
||||
while (FindNextVolumeW (sh, vol, 64));
|
||||
FindVolumeClose (sh);
|
||||
}
|
||||
|
||||
wchar_t *fixup_if_match (wchar_t *path)
|
||||
@ -640,11 +644,17 @@ struct dos_drive_mappings
|
||||
}
|
||||
/* Then test local drives. */
|
||||
for (mapping *m = mappings; m; m = m->next)
|
||||
if (!wcsncmp (m->mapping, path, m->len))
|
||||
if (!wcsncmp (m->ntdevpath, path, m->ntlen))
|
||||
{
|
||||
path += m->len - 2;
|
||||
path[0] = m->drive_letter;
|
||||
path[1] = L':';
|
||||
wchar_t *tmppath;
|
||||
|
||||
if (m->ntlen > m->doslen)
|
||||
wcsncpy (path += m->ntlen - m->doslen, m->dospath, m->doslen);
|
||||
else if ((tmppath = wcsdup (path + m->ntlen)) != NULL)
|
||||
{
|
||||
wcpcpy (wcpcpy (path, m->dospath), tmppath);
|
||||
free (tmppath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return path;
|
||||
@ -656,7 +666,9 @@ struct dos_drive_mappings
|
||||
for (mapping *m = mappings; m; m = n)
|
||||
{
|
||||
n = m->next;
|
||||
free (m);
|
||||
free (m->dospath);
|
||||
free (m->ntdevpath);
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user