* Makefile.in (cygpath.exe): Add rule to link cygpath against ntdll.dll.
* cygpath.cc: Include DDK headers. (RtlAllocateUnicodeString): New static inline function. (get_device_name): New static function to evaluate DOS path from native NT path. (get_device_paths): New function to do the same for path lists. (doit): Call get_device_paths/get_device_name where appropriate.
This commit is contained in:
parent
2ebf115df9
commit
2dba45f4aa
|
@ -1,3 +1,13 @@
|
||||||
|
2006-08-02 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* Makefile.in (cygpath.exe): Add rule to link cygpath against ntdll.dll.
|
||||||
|
* cygpath.cc: Include DDK headers.
|
||||||
|
(RtlAllocateUnicodeString): New static inline function.
|
||||||
|
(get_device_name): New static function to evaluate DOS path from
|
||||||
|
native NT path.
|
||||||
|
(get_device_paths): New function to do the same for path lists.
|
||||||
|
(doit): Call get_device_paths/get_device_name where appropriate.
|
||||||
|
|
||||||
2006-07-30 Ilya Bobir <ilya@po4ta.com>
|
2006-07-30 Ilya Bobir <ilya@po4ta.com>
|
||||||
|
|
||||||
* cygpath.cc (get_long_name): Fallback to get_long_path_name_w32impl.
|
* cygpath.cc (get_long_name): Fallback to get_long_path_name_w32impl.
|
||||||
|
|
|
@ -208,6 +208,14 @@ else
|
||||||
$(CXX) -o $@ ${wordlist 1,3,$^} -B$(cygwin_build)/ $(DUMPER_LDFLAGS)
|
$(CXX) -o $@ ${wordlist 1,3,$^} -B$(cygwin_build)/ $(DUMPER_LDFLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
cygpath.exe: cygpath.o $(ALL_DEP_LDLIBS)
|
||||||
|
ifdef VERBOSE
|
||||||
|
$(CXX) -o $@ ${firstword $^} -B$(cygwin_build)/ $(ALL_LDFLAGS) -lntdll
|
||||||
|
else
|
||||||
|
@echo $(CXX) -o $@ ${firstword $^} ${filter-out -B%, $(ALL_LDFLAGS) -ntdll};\
|
||||||
|
$(CXX) -o $@ ${firstword $^} -B$(cygwin_build)/ $(ALL_LDFLAGS) -ntdll
|
||||||
|
endif
|
||||||
|
|
||||||
%.exe: %.o $(ALL_DEP_LDLIBS)
|
%.exe: %.o $(ALL_DEP_LDLIBS)
|
||||||
ifdef VERBOSE
|
ifdef VERBOSE
|
||||||
$(CXX) -o $@ ${firstword $^} -B$(cygwin_build)/ $(ALL_LDFLAGS)
|
$(CXX) -o $@ ${firstword $^} -B$(cygwin_build)/ $(ALL_LDFLAGS)
|
||||||
|
|
|
@ -21,6 +21,9 @@ details. */
|
||||||
#include <sys/cygwin.h>
|
#include <sys/cygwin.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ddk/winddk.h>
|
||||||
|
#include <ddk/ntifs.h>
|
||||||
|
|
||||||
static const char version[] = "$Revision$";
|
static const char version[] = "$Revision$";
|
||||||
|
|
||||||
|
@ -109,6 +112,161 @@ Other options:\n\
|
||||||
exit (ignore_flag ? 0 : status);
|
exit (ignore_flag ? 0 : status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN
|
||||||
|
RtlAllocateUnicodeString (PUNICODE_STRING uni, ULONG size)
|
||||||
|
{
|
||||||
|
uni->Length = 0;
|
||||||
|
uni->MaximumLength = 512;
|
||||||
|
uni->Buffer = (WCHAR *) malloc (size);
|
||||||
|
return uni->Buffer != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_device_name (char *path)
|
||||||
|
{
|
||||||
|
UNICODE_STRING ntdev, tgtdev, ntdevdir;
|
||||||
|
ANSI_STRING ans;
|
||||||
|
OBJECT_ATTRIBUTES ntobj;
|
||||||
|
NTSTATUS status;
|
||||||
|
HANDLE lnk, dir;
|
||||||
|
char *ret = strdup (path);
|
||||||
|
PDIRECTORY_BASIC_INFORMATION odi = (PDIRECTORY_BASIC_INFORMATION)
|
||||||
|
alloca (4096);
|
||||||
|
BOOLEAN restart;
|
||||||
|
ULONG cont;
|
||||||
|
|
||||||
|
if (strncasecmp (path, "\\Device\\", 8))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!RtlAllocateUnicodeString (&ntdev, MAX_PATH * 2))
|
||||||
|
return ret;
|
||||||
|
if (!RtlAllocateUnicodeString (&tgtdev, MAX_PATH * 2))
|
||||||
|
return ret;
|
||||||
|
RtlInitAnsiString (&ans, path);
|
||||||
|
RtlAnsiStringToUnicodeString (&ntdev, &ans, FALSE);
|
||||||
|
|
||||||
|
/* First check if the given device name is a symbolic link itself. If so,
|
||||||
|
query it and use the new name as actual device name to search for in the
|
||||||
|
DOS device name directory. If not, just use the incoming device name. */
|
||||||
|
InitializeObjectAttributes (&ntobj, &ntdev, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
status = ZwOpenSymbolicLinkObject (&lnk, SYMBOLIC_LINK_QUERY, &ntobj);
|
||||||
|
if (NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
status = ZwQuerySymbolicLinkObject (lnk, &tgtdev, NULL);
|
||||||
|
ZwClose (lnk);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
goto out;
|
||||||
|
RtlCopyUnicodeString (&ntdev, &tgtdev);
|
||||||
|
}
|
||||||
|
else if (status != STATUS_OBJECT_TYPE_MISMATCH)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
/* There are two DOS device directories, the local and the global dir.
|
||||||
|
Try both, local first. */
|
||||||
|
RtlInitUnicodeString (&ntdevdir, i ? L"\\GLOBAL??" : L"\\??");
|
||||||
|
|
||||||
|
/* Open the directory... */
|
||||||
|
InitializeObjectAttributes (&ntobj, &ntdevdir, OBJ_CASE_INSENSITIVE,
|
||||||
|
NULL, NULL);
|
||||||
|
status = ZwOpenDirectoryObject (&dir, DIRECTORY_QUERY, &ntobj);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ...and scan it. */
|
||||||
|
for (restart = TRUE, cont = 0;
|
||||||
|
NT_SUCCESS (ZwQueryDirectoryObject (dir, odi, 4096, TRUE,
|
||||||
|
restart, &cont, NULL));
|
||||||
|
restart = FALSE)
|
||||||
|
{
|
||||||
|
/* For each entry check if it's a symbolic link. */
|
||||||
|
InitializeObjectAttributes (&ntobj, &odi->ObjectName,
|
||||||
|
OBJ_CASE_INSENSITIVE, dir, NULL);
|
||||||
|
status = ZwOpenSymbolicLinkObject (&lnk, SYMBOLIC_LINK_QUERY, &ntobj);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
continue;
|
||||||
|
tgtdev.Length = 0;
|
||||||
|
tgtdev.MaximumLength = 512;
|
||||||
|
/* If so, query it and compare the target of the symlink with the
|
||||||
|
incoming device name. */
|
||||||
|
status = ZwQuerySymbolicLinkObject (lnk, &tgtdev, NULL);
|
||||||
|
ZwClose (lnk);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
continue;
|
||||||
|
if (RtlEqualUnicodeString (&ntdev, &tgtdev, TRUE))
|
||||||
|
{
|
||||||
|
/* If the comparison succeeds, the name of the directory entry is
|
||||||
|
a valid DOS device name, if prepended with "\\.\". Return that
|
||||||
|
valid DOS path. */
|
||||||
|
ULONG len = RtlUnicodeStringToAnsiSize (&odi->ObjectName);
|
||||||
|
ret = (char *) malloc (len + 4);
|
||||||
|
strcpy (ret, "\\\\.\\");
|
||||||
|
ans.Length = 0;
|
||||||
|
ans.MaximumLength = len;
|
||||||
|
ans.Buffer = ret + 4;
|
||||||
|
RtlUnicodeStringToAnsiString (&ans, &odi->ObjectName, FALSE);
|
||||||
|
ZwClose (dir);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ZwClose (dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free (tgtdev.Buffer);
|
||||||
|
free (ntdev.Buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_device_paths (char *path)
|
||||||
|
{
|
||||||
|
char *sbuf;
|
||||||
|
char *ptr;
|
||||||
|
int n = 1;
|
||||||
|
|
||||||
|
ptr = path;
|
||||||
|
while ((ptr = strchr (ptr, ';')))
|
||||||
|
{
|
||||||
|
ptr++;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *paths[n];
|
||||||
|
DWORD acc = 0;
|
||||||
|
int i;
|
||||||
|
if (!n)
|
||||||
|
return strdup ("");
|
||||||
|
|
||||||
|
for (i = 0, ptr = path; ptr; i++)
|
||||||
|
{
|
||||||
|
char *next = ptr;
|
||||||
|
ptr = strchr (ptr, ';');
|
||||||
|
if (ptr)
|
||||||
|
*ptr++ = 0;
|
||||||
|
paths[i] = get_device_name (next);
|
||||||
|
acc += strlen (paths[i]) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sbuf = (char *) malloc (acc + 1);
|
||||||
|
if (sbuf == NULL)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: out of memory\n", prog_name);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sbuf[0] = '\0';
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
strcat (strcat (sbuf, paths[i]), ";");
|
||||||
|
free (paths[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
strchr (sbuf, '\0')[-1] = '\0';
|
||||||
|
return sbuf;
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
get_short_paths (char *path)
|
get_short_paths (char *path)
|
||||||
{
|
{
|
||||||
|
@ -487,6 +645,7 @@ doit (char *filename)
|
||||||
err = cygwin_posix_to_win32_path_list (filename, buf);
|
err = cygwin_posix_to_win32_path_list (filename, buf);
|
||||||
if (err)
|
if (err)
|
||||||
/* oops */;
|
/* oops */;
|
||||||
|
buf = get_device_paths (buf);
|
||||||
if (shortname_flag)
|
if (shortname_flag)
|
||||||
buf = get_short_paths (buf);
|
buf = get_short_paths (buf);
|
||||||
if (longname_flag)
|
if (longname_flag)
|
||||||
|
@ -518,6 +677,7 @@ doit (char *filename)
|
||||||
}
|
}
|
||||||
if (!unix_flag)
|
if (!unix_flag)
|
||||||
{
|
{
|
||||||
|
buf = get_device_name (buf);
|
||||||
if (shortname_flag)
|
if (shortname_flag)
|
||||||
buf = get_short_name (buf);
|
buf = get_short_name (buf);
|
||||||
if (longname_flag)
|
if (longname_flag)
|
||||||
|
|
Loading…
Reference in New Issue