* 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>
|
||||
|
||||
* 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)
|
||||
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)
|
||||
ifdef VERBOSE
|
||||
$(CXX) -o $@ ${firstword $^} -B$(cygwin_build)/ $(ALL_LDFLAGS)
|
||||
|
@ -21,6 +21,9 @@ details. */
|
||||
#include <sys/cygwin.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ddk/winddk.h>
|
||||
#include <ddk/ntifs.h>
|
||||
|
||||
static const char version[] = "$Revision$";
|
||||
|
||||
@ -109,6 +112,161 @@ Other options:\n\
|
||||
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 *
|
||||
get_short_paths (char *path)
|
||||
{
|
||||
@ -487,6 +645,7 @@ doit (char *filename)
|
||||
err = cygwin_posix_to_win32_path_list (filename, buf);
|
||||
if (err)
|
||||
/* oops */;
|
||||
buf = get_device_paths (buf);
|
||||
if (shortname_flag)
|
||||
buf = get_short_paths (buf);
|
||||
if (longname_flag)
|
||||
@ -518,6 +677,7 @@ doit (char *filename)
|
||||
}
|
||||
if (!unix_flag)
|
||||
{
|
||||
buf = get_device_name (buf);
|
||||
if (shortname_flag)
|
||||
buf = get_short_name (buf);
|
||||
if (longname_flag)
|
||||
|
Loading…
Reference in New Issue
Block a user