Implemented _wfullpath.
diff --git a/dlls/msvcrt/dir.c b/dlls/msvcrt/dir.c index abf27d5..22dfba6 100644 --- a/dlls/msvcrt/dir.c +++ b/dlls/msvcrt/dir.c
@@ -512,6 +512,171 @@ } /* INTERNAL: Helper for _fullpath. Modified PD code from 'snippets'. */ +static void wmsvcrt_fln_fix(MSVCRT_wchar_t *path) +{ + int dir_flag = 0, root_flag = 0; + MSVCRT_wchar_t *r, *p, *q, *s; + MSVCRT_wchar_t szbsdot[] = { '\\', '.', 0 }; + + /* Skip drive */ + if (NULL == (r = strrchrW(path, ':'))) + r = path; + else + ++r; + + /* Ignore leading slashes */ + while ('\\' == *r) + if ('\\' == r[1]) + strcpyW(r, &r[1]); + else + { + root_flag = 1; + ++r; + } + + p = r; /* Change "\\" to "\" */ + while (NULL != (p = strchrW(p, '\\'))) + if ('\\' == p[1]) + strcpyW(p, &p[1]); + else + ++p; + + while ('.' == *r) /* Scrunch leading ".\" */ + { + if ('.' == r[1]) + { + /* Ignore leading ".." */ + for (p = (r += 2); *p && (*p != '\\'); ++p) + ; + } + else + { + for (p = r + 1 ;*p && (*p != '\\'); ++p) + ; + } + strcpyW(r, p + ((*p) ? 1 : 0)); + } + + while ('\\' == path[strlenW(path)-1]) /* Strip last '\\' */ + { + dir_flag = 1; + path[strlenW(path)-1] = '\0'; + } + + s = r; + + /* Look for "\." in path */ + + while (NULL != (p = strstrW(s, szbsdot))) + { + if ('.' == p[2]) + { + /* Execute this section if ".." found */ + q = p - 1; + while (q > r) /* Backup one level */ + { + if (*q == '\\') + break; + --q; + } + if (q > r) + { + strcpyW(q, p + 3); + s = q; + } + else if ('.' != *q) + { + strcpyW(q + ((*q == '\\') ? 1 : 0), + p + 3 + ((*(p + 3)) ? 1 : 0)); + s = q; + } + else s = ++p; + } + else + { + /* Execute this section if "." found */ + q = p + 2; + for ( ;*q && (*q != '\\'); ++q) + ; + strcpyW (p, q); + } + } + + if (root_flag) /* Embedded ".." could have bubbled up to root */ + { + for (p = r; *p && ('.' == *p || '\\' == *p); ++p) + ; + if (r != p) + strcpyW(r, p); + } + + if (dir_flag) + { + MSVCRT_wchar_t szbs[] = { '\\', 0 }; + + strcatW(path, szbs); + } +} + +/********************************************************************* + * _wfullpath (MSVCRT.@) + */ +MSVCRT_wchar_t *_wfullpath(MSVCRT_wchar_t * absPath, const MSVCRT_wchar_t* relPath, unsigned int size) +{ + MSVCRT_wchar_t drive[5],dir[MAX_PATH],file[MAX_PATH],ext[MAX_PATH]; + MSVCRT_wchar_t res[MAX_PATH]; + size_t len; + MSVCRT_wchar_t szbs[] = { '\\', 0 }; + + + res[0] = '\0'; + + if (!relPath || !*relPath) + return _wgetcwd(absPath, size); + + if (size < 4) + { + *MSVCRT__errno() = MSVCRT_ERANGE; + return NULL; + } + + TRACE(":resolving relative path '%s'\n",debugstr_w(relPath)); + + _wsplitpath(relPath, drive, dir, file, ext); + + /* Get Directory and drive into 'res' */ + if (!dir[0] || (dir[0] != '/' && dir[0] != '\\')) + { + /* Relative or no directory given */ + _wgetdcwd(drive[0] ? toupper(drive[0]) - 'A' + 1 : 0, res, MAX_PATH); + strcatW(res,szbs); + if (dir[0]) + strcatW(res,dir); + if (drive[0]) + res[0] = drive[0]; /* If given a drive, preserve the letter case */ + } + else + { + strcpyW(res,drive); + strcatW(res,dir); + } + + strcatW(res,szbs); + strcatW(res, file); + strcatW(res, ext); + wmsvcrt_fln_fix(res); + + len = strlenW(res); + if (len >= MAX_PATH || len >= (size_t)size) + return NULL; /* FIXME: errno? */ + + if (!absPath) + return _wcsdup(res); + strcpyW(absPath,res); + return absPath; +} + +/* INTERNAL: Helper for _fullpath. Modified PD code from 'snippets'. */ static void msvcrt_fln_fix(char *path) { int dir_flag = 0, root_flag = 0;
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 51e8a35..1838558 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec
@@ -521,7 +521,7 @@ @ cdecl _wfopen(wstr wstr) @ stub _wfreopen #(wstr wstr ptr) @ cdecl _wfsopen(wstr wstr long) -@ stub _wfullpath #(ptr wstr long) +@ cdecl _wfullpath(ptr wstr long) @ cdecl _wgetcwd(wstr long) @ cdecl _wgetdcwd(long wstr long) @ cdecl _wgetenv(wstr)