Resent: Keep __p__environ sowehow actual

Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Sun Jul 21 15:56:00 CDT 2002


------- start of forwarded message -------
Changelog:
        dlls/msvcrt/data.c, environment.s: msvcrt_init_args, _putenv
        Take a snapshot of the environment strings when building the
        __p__environ array and update the array on calls to _putenv

-- 
Uwe Bonnes                bon at elektron.ikp.physik.tu-darmstadt.de

Free Software: If you contribute nothing, expect nothing
--
Index: wine/dlls/msvcrt/data.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/data.c,v
retrieving revision 1.16
diff -u -r1.16 data.c
--- wine/dlls/msvcrt/data.c	16 May 2002 23:16:01 -0000	1.16
+++ wine/dlls/msvcrt/data.c	8 Jul 2002 22:48:05 -0000
@@ -55,15 +55,102 @@
 WCHAR **MSVCRT___wargv;
 char *MSVCRT__acmdln;
 WCHAR *MSVCRT__wcmdln;
-char **MSVCRT__environ;
-WCHAR **MSVCRT__wenviron;
-char **MSVCRT___initenv;
-WCHAR **MSVCRT___winitenv;
+char **MSVCRT__environ = 0;
+WCHAR **MSVCRT__wenviron = 0;
+char **MSVCRT___initenv = 0;
+WCHAR **MSVCRT___winitenv = 0;
 int MSVCRT_timezone;
 int MSVCRT_app_type;
 
-static char* environ_strings;
-static WCHAR* wenviron_strings;
+/* Get a snapshot of the current environment 
+ * and construct the __p__environ array 
+ *
+ * The pointer returned from GetEnvironmentStrings may get invalid when
+ * some other module cause a reallocation of the env-variable block
+ * 
+ * blk is an array of pointers to environment strings, ending with a NULL
+ * and after that the actual copy of the environment strings, ending in a \0
+ */
+char ** SnapshotOfEnvironmentA(char **blk)
+{
+  char* environ_strings = GetEnvironmentStringsA();
+  int count = 1, len = 1, i = 0; /* keep space for the trailing NULLS */
+  char *ptr;
+
+  environ_strings = HeapAlloc(GetProcessHeap(), 0,100);
+  HeapFree(GetProcessHeap(), 0, environ_strings);
+  environ_strings = GetEnvironmentStringsA();
+  for (ptr = environ_strings; *ptr; ptr += strlen(ptr) + 1)
+  {
+    count++;
+    len += strlen(ptr) + 1;
+  }
+  if (blk)
+    {
+      if (HeapSize( GetProcessHeap(), 0, blk) < count* sizeof(char*)
+	  + len * sizeof(char))
+	blk = HeapReAlloc( GetProcessHeap(), 0, blk, count* sizeof(char*) +
+		     len * sizeof(char));
+    }
+  else
+    blk = HeapAlloc(GetProcessHeap(), 0, count* sizeof(char*) 
+		    + len * sizeof(char));
+  if (blk)
+    {
+      if (count)
+	{
+	  memcpy(&blk[count],environ_strings,len  * sizeof(char));
+	  for (ptr = (char*) &blk[count]; *ptr; ptr += strlen(ptr) + 1)
+	    {
+	      blk[i++] = ptr;
+	    }
+	}
+      blk[i] = NULL;
+    }
+  FreeEnvironmentStringsA(environ_strings);
+  environ_strings = HeapAlloc(GetProcessHeap(), 0,100);
+  HeapFree(GetProcessHeap(), 0, environ_strings);
+  return blk;
+}  
+
+WCHAR ** SnapshotOfEnvironmentW(WCHAR **wblk)
+{
+  WCHAR* wenviron_strings = GetEnvironmentStringsW();
+  int count = 1, len = 1, i = 0; /* keep space for the trailing NULLS */
+  WCHAR *wptr;
+
+  for (wptr = wenviron_strings; *wptr; wptr += lstrlenW(wptr) + 1)
+  {
+    count++;
+    len += lstrlenW(wptr) + 1;
+  }
+  if (wblk)
+    {
+      if (HeapSize( GetProcessHeap(), 0, wblk) < count* sizeof(WCHAR*) 
+	  + len * sizeof(WCHAR))
+	wblk = HeapReAlloc( GetProcessHeap(), 0, wblk, count* sizeof(WCHAR*)
+		     + len * sizeof(WCHAR));
+    }
+  else
+    wblk = HeapAlloc(GetProcessHeap(), 0, count* sizeof(WCHAR*) 
+		     + len * sizeof(WCHAR));
+  if (wblk)
+    {
+      if (count)
+	{
+	  memcpy(&wblk[count],wenviron_strings,len * sizeof(WCHAR));
+	  for (wptr = (WCHAR*)&wblk[count]; *wptr; wptr += lstrlenW(wptr) + 1)
+	    {
+	      wblk[i++] = wptr;
+	    }
+	}
+      wblk[i] = NULL;
+    }
+  FreeEnvironmentStringsW(wenviron_strings);
+  wenviron_strings = HeapAlloc(GetProcessHeap(), 0,100);
+  HeapFree(GetProcessHeap(), 0, wenviron_strings);
+  return wblk;
+}  
 
 typedef void (*_INITTERMFUN)(void);
 
@@ -125,12 +212,22 @@
 /*********************************************************************
  *		__p__environ (MSVCRT.@)
  */
-char*** __p__environ(void) { return &MSVCRT__environ; }
+char*** __p__environ(void) 
+{
+  if (!MSVCRT__environ)
+    MSVCRT__environ = SnapshotOfEnvironmentA(NULL);
+  return &MSVCRT__environ; 
+}
 
 /*********************************************************************
  *		__p__wenviron (MSVCRT.@)
  */
-WCHAR*** __p__wenviron(void) { return &MSVCRT__wenviron; }
+WCHAR*** __p__wenviron(void) 
+{ 
+  if (!MSVCRT__wenviron)
+    MSVCRT__wenviron = SnapshotOfEnvironmentW(NULL);
+  return &MSVCRT__wenviron;
+}
 
 /*********************************************************************
  *		__p___initenv (MSVCRT.@)
@@ -157,7 +254,7 @@
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,str,len*sizeof(char),wstr,len* sizeof (WCHAR));
   return wstr;
 }
-
+  
 /* INTERNAL: Since we can't rely on Winelib startup code calling w/getmainargs,
  * we initialise data values during DLL loading. When called by a native
  * program we simply return the data we've already initialised. This also means
@@ -165,9 +262,6 @@
  */
 void msvcrt_init_args(void)
 {
-  char *ptr;
-  WCHAR *wptr;
-  int count;
   DWORD version;
 
   MSVCRT__acmdln = _strdup( GetCommandLineA() );
@@ -198,42 +292,9 @@
 
   /* FIXME: set app type for Winelib apps */
 
-  environ_strings = GetEnvironmentStringsA();
-  count = 1; /* for NULL sentinel */
-  for (ptr = environ_strings; *ptr; ptr += strlen(ptr) + 1)
-  {
-    count++;
-  }
-  MSVCRT__environ = HeapAlloc(GetProcessHeap(), 0, count * sizeof(char*));
-  if (MSVCRT__environ)
-  {
-    count = 0;
-    for (ptr = environ_strings; *ptr; ptr += strlen(ptr) + 1)
-    {
-      MSVCRT__environ[count++] = ptr;
-    }
-    MSVCRT__environ[count] = NULL;
-  }
-
-  MSVCRT___initenv = MSVCRT__environ;
+  MSVCRT___initenv= SnapshotOfEnvironmentA(NULL);
+  MSVCRT___winitenv= SnapshotOfEnvironmentW(NULL);
 
-  wenviron_strings = GetEnvironmentStringsW();
-  count = 1; /* for NULL sentinel */
-  for (wptr = wenviron_strings; *wptr; wptr += lstrlenW(wptr) + 1)
-  {
-    count++;
-  }
-  MSVCRT__wenviron = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR*));
-  if (MSVCRT__wenviron)
-  {
-    count = 0;
-    for (wptr = wenviron_strings; *wptr; wptr += lstrlenW(wptr) + 1)
-    {
-      MSVCRT__wenviron[count++] = wptr;
-    }
-    MSVCRT__wenviron[count] = NULL;
-  }
-  MSVCRT___winitenv = MSVCRT__wenviron;
 }
 
 
@@ -241,8 +302,10 @@
 void msvcrt_free_args(void)
 {
   /* FIXME: more things to free */
-  FreeEnvironmentStringsA(environ_strings);
-  FreeEnvironmentStringsW(wenviron_strings);
+  if (MSVCRT___initenv) HeapFree(GetProcessHeap(), 0,MSVCRT___initenv);
+  if (MSVCRT__environ) HeapFree(GetProcessHeap(), 0,MSVCRT__environ);
+  if (MSVCRT__environ) HeapFree(GetProcessHeap(), 0,MSVCRT__environ);
+  if (MSVCRT__wenviron) HeapFree(GetProcessHeap(), 0,MSVCRT__wenviron);
 }
 
 /*********************************************************************
Index: wine/dlls/msvcrt/environ.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/environ.c,v
retrieving revision 1.8
diff -u -r1.8 environ.c
--- wine/dlls/msvcrt/environ.c	9 Mar 2002 23:39:08 -0000	1.8
+++ wine/dlls/msvcrt/environ.c	8 Jul 2002 22:48:05 -0000
@@ -86,7 +86,10 @@
   FreeEnvironmentStringsW( environ );
   return NULL;
 }
-
+extern char **MSVCRT__environ;
+extern WCHAR **MSVCRT__wenviron;
+char ** SnapshotOfEnvironmentA(char **);
+WCHAR ** SnapshotOfEnvironmentW(WCHAR **);
 /*********************************************************************
  *		_putenv (MSVCRT.@)
  */
@@ -94,6 +97,7 @@
 {
  char name[256], value[512];
  char *dst = name;
+ int ret;
 
  TRACE("%s\n", str);
 
@@ -109,7 +113,13 @@
   *dst++ = *str++;
  *dst = '\0';
 
- return !SetEnvironmentVariableA(name, value[0] ? value : NULL);
+ ret = !SetEnvironmentVariableA(name, value[0] ? value : NULL);
+ /* Update the __p__environ array only when already initialized */
+ if (MSVCRT__environ)
+   MSVCRT__environ = SnapshotOfEnvironmentA(MSVCRT__environ);
+ if (MSVCRT__wenviron)
+   MSVCRT__wenviron = SnapshotOfEnvironmentW(MSVCRT__wenviron);
+ return ret;
 }
 
 /*********************************************************************
@@ -119,6 +129,7 @@
 {
  WCHAR name[256], value[512];
  WCHAR *dst = name;
+ int ret;
 
  TRACE("%s\n", debugstr_w(str));
 
@@ -134,5 +145,11 @@
   *dst++ = *str++;
  *dst = (WCHAR)L'\0';
 
- return !SetEnvironmentVariableW(name, value[0] ? value : NULL);
+ ret = !SetEnvironmentVariableW(name, value[0] ? value : NULL);
+ /* Update the __p__environ array only when already initialized */
+ if (MSVCRT__environ)
+   MSVCRT__environ = SnapshotOfEnvironmentA(MSVCRT__environ);
+ if (MSVCRT__wenviron)
+   MSVCRT__wenviron = SnapshotOfEnvironmentW(MSVCRT__wenviron);
+ return ret;
 }
------- end of forwarded message -------

-- 
Uwe Bonnes                bon at elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------



More information about the wine-patches mailing list