Aric Stewart : msvcrt: Reworked _fullpath.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jan 6 14:49:33 CST 2006


Module: wine
Branch: refs/heads/master
Commit: e09a6c8080d511fd0c4d60462da9c7b3a61245d7
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=e09a6c8080d511fd0c4d60462da9c7b3a61245d7

Author: Aric Stewart <aric at codeweavers.com>
Date:   Fri Jan  6 21:45:26 2006 +0100

msvcrt: Reworked _fullpath.
Investigation with native msvcrt revealed that it is a wrapper for
GetFullPathName and the current implementation was crashing with older
mozilla installs if the path passed in was uninitialized.

---

 dlls/msvcrt/dir.c |  315 ++++++-----------------------------------------------
 1 files changed, 38 insertions(+), 277 deletions(-)

diff --git a/dlls/msvcrt/dir.c b/dlls/msvcrt/dir.c
index a47a273..fa757ac 100644
--- a/dlls/msvcrt/dir.c
+++ b/dlls/msvcrt/dir.c
@@ -738,113 +738,6 @@ void _wsplitpath(const MSVCRT_wchar_t *i
     if (ext) strcpyW( ext, end );
 }
 
-/* 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.@)
  *
@@ -852,17 +745,23 @@ static void wmsvcrt_fln_fix(MSVCRT_wchar
  */
 MSVCRT_wchar_t *_wfullpath(MSVCRT_wchar_t * absPath, const MSVCRT_wchar_t* relPath, MSVCRT_size_t 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';
+  DWORD rc;
+  WCHAR* buffer;
+  WCHAR* lastpart;
+  BOOL alloced = FALSE;
 
   if (!relPath || !*relPath)
     return _wgetcwd(absPath, size);
 
+  if (absPath == NULL)
+  {
+      buffer = MSVCRT_malloc(MAX_PATH * sizeof(WCHAR));
+      size = MAX_PATH;
+      alloced = TRUE;
+  }
+  else
+      buffer = absPath;
+
   if (size < 4)
   {
     *MSVCRT__errno() = MSVCRT_ERANGE;
@@ -871,140 +770,16 @@ MSVCRT_wchar_t *_wfullpath(MSVCRT_wchar_
 
   TRACE(":resolving relative path '%s'\n",debugstr_w(relPath));
 
-  _wsplitpath(relPath, drive, dir, file, ext);
+  rc = GetFullPathNameW(relPath,size,buffer,&lastpart);
 
-  /* 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 */
-  }
+  if (rc > 0 && rc <= size )
+    return buffer;
   else
   {
-    strcpyW(res,drive);
-    strcatW(res,dir);
+      if (alloced)
+          MSVCRT_free(buffer);
+        return NULL;
   }
-
-  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;
-  char *r, *p, *q, *s;
-
-  /* Skip drive */
-  if (NULL == (r = strrchr(path, ':')))
-    r = path;
-  else
-    ++r;
-
-  /* Ignore leading slashes */
-  while ('\\' == *r)
-    if ('\\' == r[1])
-      strcpy(r, &r[1]);
-    else
-    {
-      root_flag = 1;
-      ++r;
-    }
-
-  p = r; /* Change "\\" to "\" */
-  while (NULL != (p = strchr(p, '\\')))
-    if ('\\' ==  p[1])
-      strcpy(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)
-        ;
-    }
-    strcpy(r, p + ((*p) ? 1 : 0));
-  }
-
-  while ('\\' == path[strlen(path)-1])   /* Strip last '\\' */
-  {
-    dir_flag = 1;
-    path[strlen(path)-1] = '\0';
-  }
-
-  s = r;
-
-  /* Look for "\." in path */
-
-  while (NULL != (p = strstr(s, "\\.")))
-  {
-    if ('.' == p[2])
-    {
-      /* Execute this section if ".." found */
-      q = p - 1;
-      while (q > r)           /* Backup one level           */
-      {
-        if (*q == '\\')
-          break;
-        --q;
-      }
-      if (q > r)
-      {
-        strcpy(q, p + 3);
-        s = q;
-      }
-      else if ('.' != *q)
-      {
-        strcpy(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)
-        ;
-      strcpy (p, q);
-    }
-  }
-
-  if (root_flag)  /* Embedded ".." could have bubbled up to root  */
-  {
-    for (p = r; *p && ('.' == *p || '\\' == *p); ++p)
-      ;
-    if (r != p)
-      strcpy(r, p);
-  }
-
-  if (dir_flag)
-    strcat(path, "\\");
 }
 
 /*********************************************************************
@@ -1024,15 +799,23 @@ static void msvcrt_fln_fix(char *path)
  */
 char *_fullpath(char * absPath, const char* relPath, unsigned int size)
 {
-  char drive[5],dir[MAX_PATH],file[MAX_PATH],ext[MAX_PATH];
-  char res[MAX_PATH];
-  size_t len;
-
-  res[0] = '\0';
+  DWORD rc;
+  char* lastpart;
+  char* buffer;
+  BOOL alloced = FALSE;
 
   if (!relPath || !*relPath)
     return _getcwd(absPath, size);
 
+  if (absPath == NULL)
+  {
+      buffer = MSVCRT_malloc(MAX_PATH);
+      size = MAX_PATH;
+      alloced = TRUE;
+  }
+  else
+      buffer = absPath;
+
   if (size < 4)
   {
     *MSVCRT__errno() = MSVCRT_ERANGE;
@@ -1041,38 +824,16 @@ char *_fullpath(char * absPath, const ch
 
   TRACE(":resolving relative path '%s'\n",relPath);
 
-  _splitpath(relPath, drive, dir, file, ext);
+  rc = GetFullPathNameA(relPath,size,buffer,&lastpart);
 
-  /* Get Directory and drive into 'res' */
-  if (!dir[0] || (dir[0] != '/' && dir[0] != '\\'))
-  {
-    /* Relative or no directory given */
-    _getdcwd(drive[0] ? toupper(drive[0]) - 'A' + 1 :  0, res, MAX_PATH);
-    strcat(res,"\\");
-    if (dir[0])
-      strcat(res,dir);
-    if (drive[0])
-      res[0] = drive[0]; /* If given a drive, preserve the letter case */
-  }
+  if (rc > 0 && rc <= size)
+    return buffer;
   else
   {
-    strcpy(res,drive);
-    strcat(res,dir);
+      if (alloced)
+          MSVCRT_free(buffer);
+        return NULL;
   }
-
-  strcat(res,"\\");
-  strcat(res, file);
-  strcat(res, ext);
-  msvcrt_fln_fix(res);
-
-  len = strlen(res);
-  if (len >= MAX_PATH || len >= (size_t)size)
-    return NULL; /* FIXME: errno? */
-
-  if (!absPath)
-    return _strdup(res);
-  strcpy(absPath,res);
-  return absPath;
 }
 
 /*********************************************************************




More information about the wine-cvs mailing list