------- 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@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@elektron.ikp.physik.tu-darmstadt.de Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt --------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------