[patch 6 of 7]: 0006-Rewrite-with-locking-of-getcwd-family-functions

Kai Tietz ktietz70 at googlemail.com
Thu Dec 29 10:12:54 CST 2011


Hi,

this fixth patch adds locking support for getdcwd faimily routines (as
extension part for patch 5). It fixes some quirks about unhandled
error-checkings and AFAICS also corrects the handling of function
called with valid buf and size argument.

Regards,
Kai
-------------- next part --------------
From c69f2a4d918a6f20c31be63827d0a5c1a032abdf Mon Sep 17 00:00:00 2001
From: Kai Tietz <ktietz70 at googlemail.com>
Date: Thu, 29 Dec 2011 16:10:31 +0100
Subject: Rewrite with locking of getcwd-family functions

---
 dlls/msvcrt/dir.c |  157 +++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 121 insertions(+), 36 deletions(-)

diff --git a/dlls/msvcrt/dir.c b/dlls/msvcrt/dir.c
index 833d9d7..223439a 100644
--- a/dlls/msvcrt/dir.c
+++ b/dlls/msvcrt/dir.c
@@ -1047,39 +1047,80 @@ MSVCRT_wchar_t* CDECL MSVCRT__wgetcwd(MSVCRT_wchar_t * buf, int size)
  */
 char* CDECL MSVCRT__getdcwd(int drive, char * buf, int size)
 {
-  static char* dummy;
+  char drivespec[] = {'A', ':', 0};
+  char s[4], *p, *fname;
+  int i, l;
+
+  if (buf && size <= 0)
+    {
+      *MSVCRT__errno() = MSVCRT_EINVAL;
+      return NULL;
+    }
 
   TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
 
   if (!drive || drive == MSVCRT__getdrive())
     return MSVCRT__getcwd(buf,size); /* current */
-  else
+
+  _lock (_ENV_LOCK);
+
+  drivespec[0] += drive - 1;
+  if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
   {
-    char dir[MAX_PATH];
-    char drivespec[] = {'A', ':', 0};
-    int dir_len;
+    *MSVCRT___doserrno() = ERROR_INVALID_DRIVE;
+    *MSVCRT__errno() = MSVCRT_EACCES;
+    _unlock (_ENV_LOCK);
+    return NULL;
+  }
 
-    drivespec[0] += drive - 1;
-    if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
+  if (buf)
     {
-      *MSVCRT__errno() = MSVCRT_EACCES;
-      return NULL;
+      buf[0] = 0;
+      i = size;
     }
+  strcpy (s, "A:.");
+  s[0] += drive - 1;
 
-    dir_len = GetFullPathNameA(drivespec,MAX_PATH,dir,&dummy);
-    if (dir_len >= size || dir_len < 1)
+  if ((l = GetFullPathNameA (s, i, buf, &fname)) == 0)
+  {
+    msvcrt_set_errno (GetLastError ());
+    _unlock (_ENV_LOCK);
+    return NULL;
+  }
+
+  if (buf != NULL)
+  {
+    if (l < i)
     {
-      *MSVCRT__errno() = MSVCRT_ERANGE;
-      return NULL; /* buf too small */
+      _unlock (_ENV_LOCK);
+      return buf;
     }
 
-    TRACE(":returning '%s'\n", dir);
-    if (!buf)
-      return MSVCRT__strdup(dir); /* allocate */
+    *MSVCRT__errno() = MSVCRT_ERANGE;
+    *buf = 0;
+    _unlock (_ENV_LOCK);
+    return NULL;
+  }
 
-    strcpy(buf,dir);
+  if (l > size)
+    size = l;
+
+  if ((p = (char *) MSVCRT_malloc (size)) == NULL)
+  {
+    msvcrt_set_errno (ERROR_NOT_ENOUGH_MEMORY);
+    _unlock (_ENV_LOCK);
+    return NULL;
   }
-  return buf;
+  memset (p, 0, size);
+  l = GetFullPathNameA (s, size, p, &fname);
+  if (!l || l >= size)
+  {
+    msvcrt_set_errno (GetLastError ());
+    _unlock (_ENV_LOCK);
+    return NULL;
+  }
+  _unlock (_ENV_LOCK);
+  return p;
 }
 
 /*********************************************************************
@@ -1089,38 +1130,82 @@ char* CDECL MSVCRT__getdcwd(int drive, char * buf, int size)
  */
 MSVCRT_wchar_t* CDECL MSVCRT__wgetdcwd(int drive, MSVCRT_wchar_t * buf, int size)
 {
-  static MSVCRT_wchar_t* dummy;
+  char drivespec[] = {'A', ':', 0};
+  MSVCRT_wchar_t s[4], *p, *fname;
+  int i, l;
+
+  if (buf && size <= 0)
+    {
+      *MSVCRT__errno() = MSVCRT_EINVAL;
+      return NULL;
+    }
 
   TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
 
   if (!drive || drive == MSVCRT__getdrive())
     return MSVCRT__wgetcwd(buf,size); /* current */
-  else
+
+  _lock (_ENV_LOCK);
+
+  drivespec[0] += drive - 1;
+  if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
   {
-    MSVCRT_wchar_t dir[MAX_PATH];
-    MSVCRT_wchar_t drivespec[4] = {'A', ':', '\\', 0};
-    int dir_len;
+    *MSVCRT___doserrno() = ERROR_INVALID_DRIVE;
+    *MSVCRT__errno() = MSVCRT_EACCES;
+    _unlock (_ENV_LOCK);
+    return NULL;
+  }
 
-    drivespec[0] += drive - 1;
-    if (GetDriveTypeW(drivespec) < DRIVE_REMOVABLE)
+  if (buf)
     {
-      *MSVCRT__errno() = MSVCRT_EACCES;
-      return NULL;
+      buf[0] = 0;
+      i = size;
     }
+  s[0] = 'A' + drive - 1;
+  s[1] = ':';
+  s[2] = '.';
+  s[3] = 0;
 
-    dir_len = GetFullPathNameW(drivespec,MAX_PATH,dir,&dummy);
-    if (dir_len >= size || dir_len < 1)
+  if ((l = GetFullPathNameW (s, i, buf, &fname)) == 0)
+  {
+    msvcrt_set_errno (GetLastError ());
+    _unlock (_ENV_LOCK);
+    return NULL;
+  }
+
+  if (buf != NULL)
+  {
+    if (l < i)
     {
-      *MSVCRT__errno() = MSVCRT_ERANGE;
-      return NULL; /* buf too small */
+      _unlock (_ENV_LOCK);
+      return buf;
     }
 
-    TRACE(":returning %s\n", debugstr_w(dir));
-    if (!buf)
-      return MSVCRT__wcsdup(dir); /* allocate */
-    strcpyW(buf,dir);
+    *MSVCRT__errno() = MSVCRT_ERANGE;
+    *buf = 0;
+    _unlock (_ENV_LOCK);
+    return NULL;
   }
-  return buf;
+
+  if (l > size)
+    size = l;
+
+  if ((p = (char *) MSVCRT_malloc (size * sizeof (MSVCRT_wchar_t))) == NULL)
+  {
+    msvcrt_set_errno (ERROR_NOT_ENOUGH_MEMORY);
+    _unlock (_ENV_LOCK);
+    return NULL;
+  }
+  memset (p, 0, size * sizeof (MSVCRT_wchar_t));
+  l = GetFullPathNameW (s, size, p, &fname);
+  if (!l || l >= size)
+  {
+    msvcrt_set_errno (GetLastError ());
+    _unlock (_ENV_LOCK);
+    return NULL;
+  }
+  _unlock (_ENV_LOCK);
+  return p;
 }
 
 /*********************************************************************
-- 
1.7.5.1


More information about the wine-patches mailing list