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;