* 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>
|
2011-12-12 Corinna Vinschen <vinschen@redhat.com>
|
||||||
|
|
||||||
* fhandler_process.cc (dos_drive_mappings::dos_drive_mappings): Fully
|
* fhandler_process.cc (dos_drive_mappings::dos_drive_mappings): Fully
|
||||||
|
|
|
@ -549,84 +549,88 @@ struct dos_drive_mappings
|
||||||
struct mapping
|
struct mapping
|
||||||
{
|
{
|
||||||
mapping *next;
|
mapping *next;
|
||||||
int len;
|
size_t doslen;
|
||||||
wchar_t drive_letter;
|
size_t ntlen;
|
||||||
wchar_t mapping[1];
|
wchar_t *dospath;
|
||||||
|
wchar_t *ntdevpath;
|
||||||
};
|
};
|
||||||
mapping *mappings;
|
mapping *mappings;
|
||||||
|
|
||||||
dos_drive_mappings ()
|
dos_drive_mappings ()
|
||||||
: mappings(0)
|
: mappings(0)
|
||||||
{
|
{
|
||||||
/* The logical drive strings buffer holds a list of (at most 26)
|
tmp_pathbuf tp;
|
||||||
drive names separated by nulls and terminated by a double-null:
|
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"
|
/* 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
|
||||||
The annoying part is, QueryDosDeviceW wants only "x:" rather
|
otherwise. */
|
||||||
than the "x:\" we get back from GetLogicalDriveStringsW, so
|
HANDLE sh = FindFirstVolumeW (vol, 64);
|
||||||
we'll have to strip out the trailing slash for each mapping.
|
if (sh == INVALID_HANDLE_VALUE)
|
||||||
|
debug_printf ("FindFirstVolumeW, %E");
|
||||||
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);
|
|
||||||
else
|
else
|
||||||
for (wchar_t *cur = dbuf; (*drive = *cur); cur = wcschr (cur, L'\0')+1)
|
do
|
||||||
if (QueryDosDeviceW (drive, pbuf, NT_MAX_PATH))
|
{
|
||||||
{
|
DWORD len;
|
||||||
/* The DOS drive mapping can be another symbolic link. The result
|
/* Skip drives which are not mounted. */
|
||||||
is that the mapping won't work since the section name is the
|
if (!GetVolumePathNamesForVolumeNameW (vol, mounts, NT_MAX_PATH, &len)
|
||||||
name after resolving all symbolic links. So we have to resolve
|
|| mounts[0] == L'\0')
|
||||||
symbolic links here, too. */
|
continue;
|
||||||
for (int syml_cnt = 0; syml_cnt < SYMLOOP_MAX; ++syml_cnt)
|
*wcsrchr (vol, L'\\') = L'\0';
|
||||||
{
|
if (QueryDosDeviceW (vol + 4, devpath, NT_MAX_PATH))
|
||||||
UNICODE_STRING upath;
|
{
|
||||||
OBJECT_ATTRIBUTES attr;
|
/* The DOS drive mapping can be another symbolic link. If so,
|
||||||
NTSTATUS status;
|
the mapping won't work since the section name is the name
|
||||||
HANDLE h;
|
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);
|
RtlInitUnicodeString (&upath, devpath);
|
||||||
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
|
InitializeObjectAttributes (&attr, &upath,
|
||||||
NULL, NULL);
|
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY,
|
status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY,
|
||||||
&attr);
|
&attr);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
break;
|
break;
|
||||||
RtlInitEmptyUnicodeString (&upath, pbuf,
|
RtlInitEmptyUnicodeString (&upath, devpath, (NT_MAX_PATH - 1)
|
||||||
(NT_MAX_PATH - 1) * sizeof (WCHAR));
|
* sizeof (WCHAR));
|
||||||
status = NtQuerySymbolicLinkObject (h, &upath, NULL);
|
status = NtQuerySymbolicLinkObject (h, &upath, NULL);
|
||||||
NtClose (h);
|
NtClose (h);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
break;
|
break;
|
||||||
pbuf[upath.Length / sizeof (WCHAR)] = L'\0';
|
devpath[upath.Length / sizeof (WCHAR)] = L'\0';
|
||||||
}
|
}
|
||||||
size_t plen = wcslen (pbuf);
|
mapping *m = new mapping ();
|
||||||
size_t psize = plen * sizeof (wchar_t);
|
if (m)
|
||||||
debug_printf ("DOS drive %ls maps to %ls", drive, pbuf);
|
{
|
||||||
mapping *m = (mapping*) malloc (sizeof (mapping) + psize);
|
m->dospath = wcsdup (mounts);
|
||||||
if (m)
|
m->ntdevpath = wcsdup (devpath);
|
||||||
{
|
if (!m->dospath || !m->ntdevpath)
|
||||||
m->next = mappings;
|
{
|
||||||
m->len = plen;
|
free (m->dospath);
|
||||||
m->drive_letter = *drive;
|
free (m->ntdevpath);
|
||||||
memcpy (m->mapping, pbuf, psize + sizeof (wchar_t));
|
delete m;
|
||||||
mappings = m;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
m->doslen = wcslen (m->dospath);
|
||||||
else
|
m->dospath[--m->doslen] = L'\0'; /* Drop trailing backslash */
|
||||||
debug_printf ("Unable to determine the native mapping for %ls "
|
m->ntlen = wcslen (m->ntdevpath);
|
||||||
"(error %lu)", drive, GetLastError ());
|
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)
|
wchar_t *fixup_if_match (wchar_t *path)
|
||||||
|
@ -640,11 +644,17 @@ struct dos_drive_mappings
|
||||||
}
|
}
|
||||||
/* Then test local drives. */
|
/* Then test local drives. */
|
||||||
for (mapping *m = mappings; m; m = m->next)
|
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;
|
wchar_t *tmppath;
|
||||||
path[0] = m->drive_letter;
|
|
||||||
path[1] = L':';
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
|
@ -656,7 +666,9 @@ struct dos_drive_mappings
|
||||||
for (mapping *m = mappings; m; m = n)
|
for (mapping *m = mappings; m; m = n)
|
||||||
{
|
{
|
||||||
n = m->next;
|
n = m->next;
|
||||||
free (m);
|
free (m->dospath);
|
||||||
|
free (m->ntdevpath);
|
||||||
|
delete m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue