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