* wide_path.h (class wide_path): New class to convert Windows path

to WCHAR win32 path, including long path conversion if necessary.
	* cygcheck.cc: Use class wide_path throughout to call Win32 functions
	taking potentially long filenames.
	(display_error): Use snprintf rather than sprintf.
	(display_error_fmt): Ditto.
	(dump_sysinfo): Use FindFirstFileW/FindNextFileW.
	* cygpath.cc: Use class wide_path throughout to call Win32 functions
	taking potentially long filenames.
	(get_device_name): Raise buffer size to take long pathnames.
	(get_short_paths): Convert to using GetShortPathNameW.
	(get_short_name): Ditto.
	(get_long_path_name_w32impl): Convert to equivalent of GetLongPathNameW.
	(get_long_name): Convert to using GetLongPathNameW.
	(do_sysfolders): Raise buffer size for POSIX pathname to PATH_MAX.
	(do_pathconv): In case of POSIX->Win32 conversion, convert to wchar_t
	Win32 path name and drop long pathname prefix if possible.
	(main): Call setlocale to accommodate wide char/multibyte conversions.
This commit is contained in:
Corinna Vinschen 2009-03-14 14:56:20 +00:00
parent f03b7b10ec
commit 26fb7ef5e4
4 changed files with 178 additions and 64 deletions

View File

@ -1,3 +1,24 @@
2009-03-14 Corinna Vinschen <corinna@vinschen.de>
* wide_path.h (class wide_path): New class to convert Windows path
to WCHAR win32 path, including long path conversion if necessary.
* cygcheck.cc: Use class wide_path throughout to call Win32 functions
taking potentially long filenames.
(display_error): Use snprintf rather than sprintf.
(display_error_fmt): Ditto.
(dump_sysinfo): Use FindFirstFileW/FindNextFileW.
* cygpath.cc: Use class wide_path throughout to call Win32 functions
taking potentially long filenames.
(get_device_name): Raise buffer size to take long pathnames.
(get_short_paths): Convert to using GetShortPathNameW.
(get_short_name): Ditto.
(get_long_path_name_w32impl): Convert to equivalent of GetLongPathNameW.
(get_long_name): Convert to using GetLongPathNameW.
(do_sysfolders): Raise buffer size for POSIX pathname to PATH_MAX.
(do_pathconv): In case of POSIX->Win32 conversion, convert to wchar_t
Win32 path name and drop long pathname prefix if possible.
(main): Call setlocale to accommodate wide char/multibyte conversions.
2009-03-14 Christopher Faylor <me+cygwin@cgf.cx> 2009-03-14 Christopher Faylor <me+cygwin@cgf.cx>
* ldd.cc: Rework to detect missing DLLs. * ldd.cc: Rework to detect missing DLLs.

View File

@ -20,6 +20,7 @@
#include <windows.h> #include <windows.h>
#include <wininet.h> #include <wininet.h>
#include "path.h" #include "path.h"
#include "wide_path.h"
#include <getopt.h> #include <getopt.h>
#include "cygwin/include/sys/cygwin.h" #include "cygwin/include/sys/cygwin.h"
#include "cygwin/include/mntent.h" #include "cygwin/include/mntent.h"
@ -167,7 +168,7 @@ static int
display_error (const char *fmt, const char *x) display_error (const char *fmt, const char *x)
{ {
char buf[4000]; char buf[4000];
sprintf (buf, fmt, x); snprintf (buf, sizeof buf, fmt, x);
return display_error (buf, false, false); return display_error (buf, false, false);
} }
@ -178,7 +179,7 @@ display_error_fmt (const char *fmt, ...)
va_list va; va_list va;
va_start (va, fmt); va_start (va, fmt);
vsprintf (buf, fmt, va); vsnprintf (buf, sizeof buf, fmt, va);
return display_error (buf, false, false); return display_error (buf, false, false);
} }
@ -306,7 +307,8 @@ pathlike::check_existence (const char *fn, int showall, int verbose,
strcat (file, ext1); strcat (file, ext1);
strcat (file, ext2); strcat (file, ext2);
if (GetFileAttributes (file) != (DWORD) - 1) wide_path wpath (file);
if (GetFileAttributesW (wpath) != (DWORD) - 1)
{ {
char *lastdot = strrchr (file, '.'); char *lastdot = strrchr (file, '.');
bool is_link = lastdot && !strcmp (lastdot, LINK_EXTENSION); bool is_link = lastdot && !strcmp (lastdot, LINK_EXTENSION);
@ -754,9 +756,10 @@ track_down (const char *file, const char *suffix, int lvl)
printf ("%s", path); printf ("%s", path);
wide_path wpath (path);
HANDLE fh = HANDLE fh =
CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, CreateFileW (wpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) if (fh == INVALID_HANDLE_VALUE)
{ {
display_error ("cannot open - '%s'\n", path); display_error ("cannot open - '%s'\n", path);
@ -788,8 +791,10 @@ track_down (const char *file, const char *suffix, int lvl)
static void static void
ls (char *f) ls (char *f)
{ {
HANDLE h = CreateFile (f, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, wide_path wpath (f);
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); HANDLE h = CreateFileW (wpath, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
BY_HANDLE_FILE_INFORMATION info; BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle (h, &info)) if (!GetFileInformationByHandle (h, &info))
@ -812,13 +817,13 @@ ls (char *f)
static char * static char *
dirname (const char *s) dirname (const char *s)
{ {
static char buf[MAX_PATH]; static char buf[PATH_MAX];
if (!s) if (!s)
return NULL; return NULL;
strncpy (buf, s, MAX_PATH); strncpy (buf, s, PATH_MAX);
buf[MAX_PATH - 1] = '\0'; // in case strlen(s) > MAX_PATH buf[PATH_MAX - 1] = '\0'; // in case strlen(s) > PATH_MAX
char *lastsep = strrchr (buf, '\\'); char *lastsep = strrchr (buf, '\\');
if (!lastsep) if (!lastsep)
return NULL; // no backslash -> no dirname return NULL; // no backslash -> no dirname
@ -835,9 +840,10 @@ find_app_on_path (const char *app, bool showall = false)
{ {
const char *papp = find_on_path (app, ".exe", showall, false, true); const char *papp = find_on_path (app, ".exe", showall, false, true);
wide_path wpath (papp);
HANDLE fh = HANDLE fh =
CreateFile (papp, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, CreateFileW (wpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) if (fh == INVALID_HANDLE_VALUE)
return NULL; return NULL;
@ -1705,14 +1711,16 @@ dump_sysinfo ()
char cygdll_path[32768]; char cygdll_path[32768];
for (pathlike *pth = paths; pth->dir; pth++) for (pathlike *pth = paths; pth->dir; pth++)
{ {
WIN32_FIND_DATA ffinfo; WIN32_FIND_DATAW ffinfo;
sprintf (tmp, "%s*.*", pth->dir); sprintf (tmp, "%s*.*", pth->dir);
HANDLE ff = FindFirstFile (tmp, &ffinfo); wide_path wpath (tmp);
HANDLE ff = FindFirstFileW (wpath, &ffinfo);
int found = (ff != INVALID_HANDLE_VALUE); int found = (ff != INVALID_HANDLE_VALUE);
found_cygwin_dll = NULL; found_cygwin_dll = NULL;
while (found) while (found)
{ {
char *f = ffinfo.cFileName; char f[FILENAME_MAX + 1];
wcstombs (f, ffinfo.cFileName, sizeof f);
if (strcasecmp (f + strlen (f) - 4, ".dll") == 0) if (strcasecmp (f + strlen (f) - 4, ".dll") == 0)
{ {
if (strncasecmp (f, "cyg", 3) == 0) if (strncasecmp (f, "cyg", 3) == 0)
@ -1731,7 +1739,7 @@ dump_sysinfo ()
ls (tmp); ls (tmp);
} }
} }
found = FindNextFile (ff, &ffinfo); found = FindNextFileW (ff, &ffinfo);
} }
if (found_cygwin_dll) if (found_cygwin_dll)
{ {

View File

@ -1,6 +1,6 @@
/* cygpath.cc -- convert pathnames between Windows and Unix format /* cygpath.cc -- convert pathnames between Windows and Unix format
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008 Red Hat, Inc. 2006, 2007, 2008, 2009 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -13,6 +13,8 @@ details. */
#include <shlobj.h> #include <shlobj.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <wchar.h>
#include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include <argz.h> #include <argz.h>
#include <limits.h> #include <limits.h>
@ -26,6 +28,7 @@ details. */
#include <ddk/ntddk.h> #include <ddk/ntddk.h>
#include <ddk/winddk.h> #include <ddk/winddk.h>
#include <ddk/ntifs.h> #include <ddk/ntifs.h>
#include "wide_path.h"
static const char version[] = "$Revision$"; static const char version[] = "$Revision$";
@ -146,9 +149,9 @@ get_device_name (char *path)
if (strncasecmp (path, "\\Device\\", 8)) if (strncasecmp (path, "\\Device\\", 8))
return ret; return ret;
if (!RtlAllocateUnicodeString (&ntdev, MAX_PATH * 2)) if (!RtlAllocateUnicodeString (&ntdev, 65536))
return ret; return ret;
if (!RtlAllocateUnicodeString (&tgtdev, MAX_PATH * 2)) if (!RtlAllocateUnicodeString (&tgtdev, 65536))
return ret; return ret;
RtlInitAnsiString (&ans, path); RtlInitAnsiString (&ans, path);
RtlAnsiStringToUnicodeString (&ntdev, &ans, FALSE); RtlAnsiStringToUnicodeString (&ntdev, &ans, FALSE);
@ -278,8 +281,8 @@ get_device_paths (char *path)
static char * static char *
get_short_paths (char *path) get_short_paths (char *path)
{ {
char *sbuf; wchar_t *sbuf;
char *sptr; wchar_t *sptr;
char *next; char *next;
char *ptr = path; char *ptr = path;
char *end = strrchr (path, 0); char *end = strrchr (path, 0);
@ -292,7 +295,8 @@ get_short_paths (char *path)
ptr = strchr (ptr, ';'); ptr = strchr (ptr, ';');
if (ptr) if (ptr)
*ptr++ = 0; *ptr++ = 0;
len = GetShortPathName (next, NULL, 0); wide_path wpath (next);
len = GetShortPathNameW (wpath, NULL, 0);
if (!len) if (!len)
{ {
fprintf (stderr, "%s: cannot create short name of %s\n", prog_name, fprintf (stderr, "%s: cannot create short name of %s\n", prog_name,
@ -301,7 +305,7 @@ get_short_paths (char *path)
} }
acc += len + 1; acc += len + 1;
} }
sptr = sbuf = (char *) malloc (acc + 1); sptr = sbuf = (wchar_t *) malloc ((acc + 1) * sizeof (wchar_t));
if (sbuf == NULL) if (sbuf == NULL)
{ {
fprintf (stderr, "%s: out of memory\n", prog_name); fprintf (stderr, "%s: out of memory\n", prog_name);
@ -310,7 +314,8 @@ get_short_paths (char *path)
ptr = path; ptr = path;
for (;;) for (;;)
{ {
len = GetShortPathName (ptr, sptr, acc); wide_path wpath (ptr);
len = GetShortPathNameW (wpath, sptr, acc);
if (!len) if (!len)
{ {
fprintf (stderr, "%s: cannot create short name of %s\n", prog_name, fprintf (stderr, "%s: cannot create short name of %s\n", prog_name,
@ -319,74 +324,88 @@ get_short_paths (char *path)
} }
ptr = strrchr (ptr, 0); ptr = strrchr (ptr, 0);
sptr = strrchr (sptr, 0); sptr = wcsrchr (sptr, 0);
if (ptr == end) if (ptr == end)
break; break;
*sptr = ';'; *sptr = L';';
++ptr, ++sptr; ++ptr, ++sptr;
acc -= len + 1; acc -= len + 1;
} }
return sbuf; len = wcstombs (NULL, sbuf, 0) + 1;
ptr = (char *) malloc (len);
if (ptr == NULL)
{
fprintf (stderr, "%s: out of memory\n", prog_name);
exit (1);
}
wcstombs (ptr, sbuf, len);
return ptr;
} }
static char * static char *
get_short_name (const char *filename) get_short_name (const char *filename)
{ {
char *sbuf, buf[MAX_PATH]; wchar_t buf[32768];
DWORD len = GetShortPathName (filename, buf, MAX_PATH); char *sbuf;
wide_path wpath (filename);
DWORD len = GetShortPathNameW (wpath, buf, 32768);
if (!len) if (!len)
{ {
fprintf (stderr, "%s: cannot create short name of %s\n", prog_name, fprintf (stderr, "%s: cannot create short name of %s\n", prog_name,
filename); filename);
exit (2); exit (2);
} }
sbuf = (char *) malloc (++len); len = wcstombs (NULL, buf, 0) + 1;
sbuf = (char *) malloc (len);
if (sbuf == NULL) if (sbuf == NULL)
{ {
fprintf (stderr, "%s: out of memory\n", prog_name); fprintf (stderr, "%s: out of memory\n", prog_name);
exit (1); exit (1);
} }
return strcpy (sbuf, buf); wcstombs (sbuf, buf, len);
return sbuf;
} }
static DWORD WINAPI static DWORD WINAPI
get_long_path_name_w32impl (LPCSTR src, LPSTR sbuf, DWORD) get_long_path_name_w32impl (LPCWSTR src, LPWSTR sbuf, DWORD)
{ {
char buf1[MAX_PATH], buf2[MAX_PATH], *ptr; wchar_t *buf1 = (wchar_t *) malloc (32768);
const char *pelem, *next; wchar_t *buf2 = (wchar_t *) malloc (32768);
WIN32_FIND_DATA w32_fd; wchar_t *ptr;
int len; const wchar_t *pelem, *next;
WIN32_FIND_DATAW w32_fd;
DWORD len;
strcpy (buf1, src); wcscpy (buf1, src);
*buf2 = 0; *buf2 = L'\0';
pelem = src; pelem = src;
ptr = buf2; ptr = buf2;
while (pelem) while (pelem)
{ {
next = pelem; next = pelem;
if (*next == '\\') if (*next == L'\\')
{ {
strcat (ptr++, "\\"); wcscat (ptr++, L"\\");
pelem++; pelem++;
if (!*pelem) if (!*pelem)
break; break;
continue; continue;
} }
pelem = strchr (next, '\\'); pelem = wcschr (next, L'\\');
len = pelem ? (pelem++ - next) : strlen (next); len = pelem ? (pelem++ - next) : wcslen (next);
strncpy (ptr, next, len); wcsncpy (ptr, next, len);
ptr[len] = 0; ptr[len] = L'\0';
if (next[1] != ':' && strcmp(next, ".") && strcmp(next, "..")) if (next[1] != L':' && wcscmp(next, L".") && wcscmp(next, L".."))
{ {
HANDLE h; HANDLE h;
h = FindFirstFile (buf2, &w32_fd); h = FindFirstFileW (buf2, &w32_fd);
if (h != INVALID_HANDLE_VALUE) if (h != INVALID_HANDLE_VALUE)
{ {
strcpy (ptr, w32_fd.cFileName); wcscpy (ptr, w32_fd.cFileName);
FindClose (h); FindClose (h);
} }
} }
ptr += strlen (ptr); ptr += wcslen (ptr);
if (pelem) if (pelem)
{ {
*ptr++ = '\\'; *ptr++ = '\\';
@ -394,22 +413,27 @@ get_long_path_name_w32impl (LPCSTR src, LPSTR sbuf, DWORD)
} }
} }
if (sbuf) if (sbuf)
strcpy (sbuf, buf2); wcscpy (sbuf, buf2);
SetLastError (0); SetLastError (0);
return strlen (buf2) + (sbuf ? 0 : 1); len = wcslen (buf2) + (sbuf ? 0 : 1);
free (buf1);
free (buf2);
return len;
} }
static char * static char *
get_long_name (const char *filename, DWORD& len) get_long_name (const char *filename, DWORD& len)
{ {
char *sbuf, buf[MAX_PATH]; char *sbuf;
wchar_t buf[32768];
static HINSTANCE k32 = LoadLibrary ("kernel32.dll"); static HINSTANCE k32 = LoadLibrary ("kernel32.dll");
static DWORD (WINAPI *GetLongPathName) (LPCSTR, LPSTR, DWORD) = static DWORD (WINAPI *GetLongPathName) (LPCWSTR, LPWSTR, DWORD) =
(DWORD (WINAPI *) (LPCSTR, LPSTR, DWORD)) GetProcAddress (k32, "GetLongPathNameA"); (DWORD (WINAPI *) (LPCWSTR, LPWSTR, DWORD)) GetProcAddress (k32, "GetLongPathNameW");
if (!GetLongPathName) if (!GetLongPathName)
GetLongPathName = get_long_path_name_w32impl; GetLongPathName = get_long_path_name_w32impl;
len = GetLongPathName (filename, buf, MAX_PATH); wide_path wpath (filename);
len = GetLongPathName (wpath, buf, 32768);
if (len == 0) if (len == 0)
{ {
DWORD err = GetLastError (); DWORD err = GetLastError ();
@ -421,21 +445,22 @@ get_long_name (const char *filename, DWORD& len)
exit (2); exit (2);
} }
else if (err == ERROR_FILE_NOT_FOUND) else if (err == ERROR_FILE_NOT_FOUND)
len = get_long_path_name_w32impl (filename, buf, MAX_PATH); get_long_path_name_w32impl (wpath, buf, 32768);
else else
{ {
buf[0] = '\0'; buf[0] = L'\0';
strncat (buf, filename, MAX_PATH - 1); wcsncat (buf, wpath, 32767);
len = strlen (buf);
} }
} }
len = wcstombs (NULL, buf, 0);
sbuf = (char *) malloc (len + 1); sbuf = (char *) malloc (len + 1);
if (!sbuf) if (!sbuf)
{ {
fprintf (stderr, "%s: out of memory\n", prog_name); fprintf (stderr, "%s: out of memory\n", prog_name);
exit (1); exit (1);
} }
return strcpy (sbuf, buf); wcstombs (sbuf, buf, len + 1);
return sbuf;
} }
static char * static char *
@ -535,7 +560,7 @@ get_user_folder (char* path, int id, int allid)
static void static void
do_sysfolders (char option) do_sysfolders (char option)
{ {
char *buf, buf1[MAX_PATH], buf2[MAX_PATH]; char *buf, buf1[MAX_PATH], buf2[PATH_MAX];
DWORD len = MAX_PATH; DWORD len = MAX_PATH;
WIN32_FIND_DATA w32_fd; WIN32_FIND_DATA w32_fd;
HINSTANCE k32; HINSTANCE k32;
@ -607,7 +632,7 @@ do_sysfolders (char option)
else if (!windows_flag) else if (!windows_flag)
{ {
if (cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, buf, buf2, if (cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, buf, buf2,
MAX_PATH)) PATH_MAX))
fprintf (stderr, "%s: error converting \"%s\" - %s\n", fprintf (stderr, "%s: error converting \"%s\" - %s\n",
prog_name, buf, strerror (errno)); prog_name, buf, strerror (errno));
else else
@ -645,17 +670,20 @@ static void
do_pathconv (char *filename) do_pathconv (char *filename)
{ {
char *buf; char *buf;
wchar_t *buf2;
DWORD len; DWORD len;
ssize_t err; ssize_t err;
cygwin_conv_path_t conv_func = cygwin_conv_path_t conv_func =
(unix_flag ? CCP_WIN_A_TO_POSIX : CCP_POSIX_TO_WIN_A) (unix_flag ? CCP_WIN_A_TO_POSIX
: (path_flag ? CCP_POSIX_TO_WIN_A
: CCP_POSIX_TO_WIN_W))
| (absolute_flag ? CCP_ABSOLUTE : CCP_RELATIVE); | (absolute_flag ? CCP_ABSOLUTE : CCP_RELATIVE);
if (!path_flag) if (!path_flag)
{ {
len = strlen (filename); len = strlen (filename);
if (len) if (len)
len += MAX_PATH + 1001; len = 32768;
else if (ignore_flag) else if (ignore_flag)
exit (0); exit (0);
else else
@ -668,6 +696,8 @@ do_pathconv (char *filename)
len = cygwin_conv_path_list (conv_func, filename, NULL, 0); len = cygwin_conv_path_list (conv_func, filename, NULL, 0);
buf = (char *) malloc (len); buf = (char *) malloc (len);
if (!unix_flag && !path_flag)
buf2 = (wchar_t *) malloc (len * sizeof (wchar_t));
if (buf == NULL) if (buf == NULL)
{ {
fprintf (stderr, "%s: out of memory\n", prog_name); fprintf (stderr, "%s: out of memory\n", prog_name);
@ -698,7 +728,8 @@ do_pathconv (char *filename)
} }
else else
{ {
err = cygwin_conv_path (conv_func, filename, buf, len); err = cygwin_conv_path (conv_func, filename,
unix_flag ? (void *) buf : (void *) buf2, len);
if (err) if (err)
{ {
fprintf (stderr, "%s: error converting \"%s\" - %s\n", fprintf (stderr, "%s: error converting \"%s\" - %s\n",
@ -707,6 +738,7 @@ do_pathconv (char *filename)
} }
if (!unix_flag) if (!unix_flag)
{ {
wcstombs (buf, buf2, 32768);
buf = get_device_name (buf); buf = get_device_name (buf);
if (shortname_flag) if (shortname_flag)
buf = get_short_name (buf); buf = get_short_name (buf);
@ -714,6 +746,15 @@ do_pathconv (char *filename)
buf = get_long_name (buf, len); buf = get_long_name (buf, len);
if (mixed_flag) if (mixed_flag)
buf = get_mixed_name (buf); buf = get_mixed_name (buf);
len = 4;
if (strncmp (buf, "\\\\?\\UNC\\", 8) == 0)
len = 6;
if (strlen (buf) < MAX_PATH + len)
{
buf += len;
if (len == 6)
*buf = '\\';
}
} }
} }
@ -938,6 +979,7 @@ main (int argc, char **argv)
{ {
int o; int o;
setlocale (LC_ALL, "");
prog_name = strrchr (argv[0], '/'); prog_name = strrchr (argv[0], '/');
if (!prog_name) if (!prog_name)
prog_name = strrchr (argv[0], '\\'); prog_name = strrchr (argv[0], '\\');

43
winsup/utils/wide_path.h Normal file
View File

@ -0,0 +1,43 @@
/* wide_path.h -- Define class wide_path to convert multibyte win32 path
to wchar_t Win32 path including long path prefix if
necessary.
Copyright 2009 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <stdlib.h>
#include <wchar.h>
class wide_path
{
wchar_t *wp;
public:
wide_path () : wp (NULL) {}
wide_path (const char *mb_path)
{
int len = mbstowcs (NULL, mb_path, 0) + 1;
wp = (wchar_t *) malloc ((len + 6) * sizeof (wchar_t));
wchar_t *wp_p = wp;
if (len >= MAX_PATH && strncmp (mb_path, "\\\\?\\", 4) != 0)
{
wcscpy (wp_p, L"\\\\?\\");
wp_p += 4;
if (strncmp (mb_path, "\\\\", 2) == 0)
{
wcscpy (wp_p, L"UNC");
wp_p += 3;
++mb_path;
--len;
}
}
mbstowcs (wp_p, mb_path, len);
}
~wide_path () { if (wp) free (wp); }
operator const wchar_t *() const { return wp; }
};