* cygpath.cc (RtlEqualUnicodePathPrefix): New helper function.
(HARDDISK_PREFIX): Move. (GLOBALROOT_PREFIX): Define. (get_device_name): Take GLOBALROOT_PREFIX into account. Improve check for path to allow filesystem access via block devices. Potentially drop \\.\ prefix if resulting path is a valid DOS pathname. (do_pathconv): Make sure to drop \\?\ prefix only if path is actually a filesystem based path. (print_version): Fix copyright.
This commit is contained in:
parent
43f65cdd7d
commit
d2cc418e6e
|
@ -1,3 +1,16 @@
|
||||||
|
2010-09-06 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* cygpath.cc (RtlEqualUnicodePathPrefix): New helper function.
|
||||||
|
(HARDDISK_PREFIX): Move.
|
||||||
|
(GLOBALROOT_PREFIX): Define.
|
||||||
|
(get_device_name): Take GLOBALROOT_PREFIX into account.
|
||||||
|
Improve check for path to allow filesystem access via block devices.
|
||||||
|
Potentially drop \\.\ prefix if resulting path is a valid DOS
|
||||||
|
pathname.
|
||||||
|
(do_pathconv): Make sure to drop \\?\ prefix only if path is
|
||||||
|
actually a filesystem based path.
|
||||||
|
(print_version): Fix copyright.
|
||||||
|
|
||||||
2010-08-28 Corinna Vinschen <corinna@vinschen.de>
|
2010-08-28 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* ldh.cc (WinMain): Change DONT_RESOLVE_DLL_REFERENCES to
|
* ldh.cc (WinMain): Change DONT_RESOLVE_DLL_REFERENCES to
|
||||||
|
|
|
@ -134,11 +134,23 @@ static inline BOOLEAN
|
||||||
RtlAllocateUnicodeString (PUNICODE_STRING uni, ULONG size)
|
RtlAllocateUnicodeString (PUNICODE_STRING uni, ULONG size)
|
||||||
{
|
{
|
||||||
uni->Length = 0;
|
uni->Length = 0;
|
||||||
uni->MaximumLength = 512;
|
uni->MaximumLength = size / sizeof (WCHAR);
|
||||||
uni->Buffer = (WCHAR *) malloc (size);
|
uni->Buffer = (WCHAR *) malloc (size);
|
||||||
return uni->Buffer != NULL;
|
return uni->Buffer != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
RtlEqualUnicodePathPrefix (PUNICODE_STRING path, PUNICODE_STRING prefix,
|
||||||
|
BOOLEAN caseinsensitive)
|
||||||
|
{
|
||||||
|
UNICODE_STRING p;
|
||||||
|
|
||||||
|
p.Length = p.MaximumLength = prefix->Length < path->Length
|
||||||
|
? prefix->Length : path->Length;
|
||||||
|
p.Buffer = path->Buffer;
|
||||||
|
return RtlEqualUnicodeString (&p, prefix, caseinsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
my_wcstombs (char *dest, const wchar_t *src, size_t n)
|
my_wcstombs (char *dest, const wchar_t *src, size_t n)
|
||||||
{
|
{
|
||||||
|
@ -148,6 +160,9 @@ my_wcstombs (char *dest, const wchar_t *src, size_t n)
|
||||||
return wcstombs (dest, src, n);
|
return wcstombs (dest, src, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HARDDISK_PREFIX L"\\Device\\Harddisk"
|
||||||
|
#define GLOBALROOT_PREFIX "\\\\.\\GLOBALROOT"
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
get_device_name (char *path)
|
get_device_name (char *path)
|
||||||
{
|
{
|
||||||
|
@ -156,18 +171,21 @@ get_device_name (char *path)
|
||||||
OBJECT_ATTRIBUTES ntobj;
|
OBJECT_ATTRIBUTES ntobj;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
HANDLE lnk, dir;
|
HANDLE lnk, dir;
|
||||||
|
bool got_one = false;
|
||||||
char *ret = strdup (path);
|
char *ret = strdup (path);
|
||||||
PDIRECTORY_BASIC_INFORMATION odi = (PDIRECTORY_BASIC_INFORMATION)
|
PDIRECTORY_BASIC_INFORMATION odi = (PDIRECTORY_BASIC_INFORMATION)
|
||||||
alloca (4096);
|
alloca (4096);
|
||||||
BOOLEAN restart;
|
BOOLEAN restart;
|
||||||
ULONG cont;
|
ULONG cont;
|
||||||
|
|
||||||
|
if (!strncasecmp (path, GLOBALROOT_PREFIX "\\", sizeof (GLOBALROOT_PREFIX)))
|
||||||
|
path += sizeof (GLOBALROOT_PREFIX) - 1;
|
||||||
if (strncasecmp (path, "\\Device\\", 8))
|
if (strncasecmp (path, "\\Device\\", 8))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!RtlAllocateUnicodeString (&ntdev, 65536))
|
if (!RtlAllocateUnicodeString (&ntdev, 65534))
|
||||||
return ret;
|
return ret;
|
||||||
if (!RtlAllocateUnicodeString (&tgtdev, 65536))
|
if (!RtlAllocateUnicodeString (&tgtdev, 65534))
|
||||||
return ret;
|
return ret;
|
||||||
RtlInitAnsiString (&ans, path);
|
RtlInitAnsiString (&ans, path);
|
||||||
RtlAnsiStringToUnicodeString (&ntdev, &ans, FALSE);
|
RtlAnsiStringToUnicodeString (&ntdev, &ans, FALSE);
|
||||||
|
@ -185,7 +203,8 @@ get_device_name (char *path)
|
||||||
goto out;
|
goto out;
|
||||||
RtlCopyUnicodeString (&ntdev, &tgtdev);
|
RtlCopyUnicodeString (&ntdev, &tgtdev);
|
||||||
}
|
}
|
||||||
else if (status != STATUS_OBJECT_TYPE_MISMATCH)
|
else if (status != STATUS_OBJECT_TYPE_MISMATCH
|
||||||
|
&& status != STATUS_OBJECT_PATH_SYNTAX_BAD)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
|
@ -221,12 +240,19 @@ get_device_name (char *path)
|
||||||
ZwClose (lnk);
|
ZwClose (lnk);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
continue;
|
continue;
|
||||||
if (RtlEqualUnicodeString (&ntdev, &tgtdev, TRUE))
|
if (tgtdev.Length /* There's actually a symlink pointing to an
|
||||||
|
empty string: \??\GLOBALROOT -> "" */
|
||||||
|
&& RtlEqualUnicodePathPrefix (&ntdev, &tgtdev, TRUE))
|
||||||
{
|
{
|
||||||
/* If the comparison succeeds, the name of the directory entry is
|
/* If the comparison succeeds, the name of the directory entry is
|
||||||
a valid DOS device name, if prepended with "\\.\". Return that
|
a valid DOS device name, if prepended with "\\.\". Return that
|
||||||
valid DOS path. */
|
valid DOS path. */
|
||||||
|
wchar_t *trailing = NULL;
|
||||||
|
if (ntdev.Length > tgtdev.Length)
|
||||||
|
trailing = ntdev.Buffer + tgtdev.Length / sizeof (WCHAR);
|
||||||
ULONG len = RtlUnicodeStringToAnsiSize (&odi->ObjectName);
|
ULONG len = RtlUnicodeStringToAnsiSize (&odi->ObjectName);
|
||||||
|
if (trailing)
|
||||||
|
len += my_wcstombs (NULL, trailing, 0);
|
||||||
free (ret);
|
free (ret);
|
||||||
ret = (char *) malloc (len + 4);
|
ret = (char *) malloc (len + 4);
|
||||||
strcpy (ret, "\\\\.\\");
|
strcpy (ret, "\\\\.\\");
|
||||||
|
@ -234,15 +260,30 @@ get_device_name (char *path)
|
||||||
ans.MaximumLength = len;
|
ans.MaximumLength = len;
|
||||||
ans.Buffer = ret + 4;
|
ans.Buffer = ret + 4;
|
||||||
RtlUnicodeStringToAnsiString (&ans, &odi->ObjectName, FALSE);
|
RtlUnicodeStringToAnsiString (&ans, &odi->ObjectName, FALSE);
|
||||||
|
if (trailing)
|
||||||
|
my_wcstombs (ans.Buffer + ans.Length, trailing,
|
||||||
|
ans.MaximumLength - ans.Length);
|
||||||
|
ans.Buffer[ans.MaximumLength - 1] = '\0';
|
||||||
|
got_one = true;
|
||||||
/* Special case for local disks: It's most feasible if the
|
/* Special case for local disks: It's most feasible if the
|
||||||
DOS device name reflects the DOS drive, so we check for this
|
DOS device name reflects the DOS drive, so we check for this
|
||||||
explicitly and only return prematurely if so. */
|
explicitly and only return prematurely if so. */
|
||||||
#define HARDDISK_PREFIX L"\\Device\\Harddisk"
|
|
||||||
if (ntdev.Length < wcslen (HARDDISK_PREFIX)
|
if (ntdev.Length < wcslen (HARDDISK_PREFIX)
|
||||||
|| wcsncasecmp (ntdev.Buffer, HARDDISK_PREFIX, 8) != 0
|
|| wcsncasecmp (ntdev.Buffer, HARDDISK_PREFIX, 8) != 0
|
||||||
|| (odi->ObjectName.Length == 2 * sizeof (WCHAR)
|
|| (odi->ObjectName.Length == 2 * sizeof (WCHAR)
|
||||||
&& odi->ObjectName.Buffer[1] == L':'))
|
&& odi->ObjectName.Buffer[1] == L':'))
|
||||||
{
|
{
|
||||||
|
if (trailing)
|
||||||
|
{
|
||||||
|
/* If there's a trailing path, it's a perfectly valid
|
||||||
|
DOS pathname without the \\.\ prefix. Unless it's
|
||||||
|
longer than MAX_PATH - 1 in which case it needs
|
||||||
|
the \\?\ prefix. */
|
||||||
|
if (len = strlen (ret + 4) >= MAX_PATH)
|
||||||
|
ret[2] = '?';
|
||||||
|
else
|
||||||
|
memmove (ret, ret + 4, strlen (ret + 4) + 1);
|
||||||
|
}
|
||||||
ZwClose (dir);
|
ZwClose (dir);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -254,6 +295,13 @@ get_device_name (char *path)
|
||||||
out:
|
out:
|
||||||
free (tgtdev.Buffer);
|
free (tgtdev.Buffer);
|
||||||
free (ntdev.Buffer);
|
free (ntdev.Buffer);
|
||||||
|
if (!got_one)
|
||||||
|
{
|
||||||
|
free (ret);
|
||||||
|
ret = (char *) malloc (sizeof (GLOBALROOT_PREFIX) + strlen (path));
|
||||||
|
if (ret)
|
||||||
|
stpcpy (stpcpy (ret, GLOBALROOT_PREFIX), path);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,10 +835,12 @@ do_pathconv (char *filename)
|
||||||
tmp = buf;
|
tmp = buf;
|
||||||
if (strncmp (buf, "\\\\?\\", 4) == 0)
|
if (strncmp (buf, "\\\\?\\", 4) == 0)
|
||||||
{
|
{
|
||||||
len = 4;
|
len = 0;
|
||||||
if (strncmp (buf + 4, "UNC\\", 4) == 0)
|
if (buf[5] == ':')
|
||||||
|
len = 4;
|
||||||
|
else if (!strncmp (buf + 4, "UNC\\", 4))
|
||||||
len = 6;
|
len = 6;
|
||||||
if (strlen (buf) < MAX_PATH + len)
|
if (len && strlen (buf) < MAX_PATH + len)
|
||||||
{
|
{
|
||||||
tmp += len;
|
tmp += len;
|
||||||
if (len == 6)
|
if (len == 6)
|
||||||
|
@ -829,7 +879,7 @@ print_version ()
|
||||||
cygpath (cygwin) %.*s\n\
|
cygpath (cygwin) %.*s\n\
|
||||||
Path Conversion Utility\n\
|
Path Conversion Utility\n\
|
||||||
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, \n\
|
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, \n\
|
||||||
2007, 2008 Red Hat, Inc.\n\
|
2007, 2008, 2009, 2010 Red Hat, Inc.\n\
|
||||||
Compiled on %s\n\
|
Compiled on %s\n\
|
||||||
", len, v, __DATE__);
|
", len, v, __DATE__);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue