Andrew Nguyen : msvcrt: Initialize environ on DLL load.
Alexandre Julliard
julliard at winehq.org
Thu Sep 30 11:23:36 CDT 2010
Module: wine
Branch: master
Commit: 285e6d249fded2a306a251550652c650f7bf81ba
URL: http://source.winehq.org/git/wine.git/?a=commit;h=285e6d249fded2a306a251550652c650f7bf81ba
Author: Andrew Nguyen <anguyen at codeweavers.com>
Date: Thu Sep 30 01:24:13 2010 -0500
msvcrt: Initialize environ on DLL load.
---
dlls/msvcrt/data.c | 15 +++--
dlls/msvcrt/environ.c | 12 +---
dlls/msvcrt/tests/environ.c | 131 ++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 142 insertions(+), 16 deletions(-)
diff --git a/dlls/msvcrt/data.c b/dlls/msvcrt/data.c
index 54dda1c..068b29f 100644
--- a/dlls/msvcrt/data.c
+++ b/dlls/msvcrt/data.c
@@ -204,8 +204,6 @@ MSVCRT_wchar_t*** CDECL __p___wargv(void) { return &MSVCRT___wargv; }
*/
char*** CDECL __p__environ(void)
{
- if (!MSVCRT__environ)
- MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(NULL);
return &MSVCRT__environ;
}
@@ -214,8 +212,6 @@ char*** CDECL __p__environ(void)
*/
MSVCRT_wchar_t*** CDECL __p__wenviron(void)
{
- if (!MSVCRT__wenviron)
- MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(NULL);
return &MSVCRT__wenviron;
}
@@ -311,9 +307,10 @@ void msvcrt_init_args(void)
MSVCRT___setlc_active = 0;
MSVCRT___unguarded_readlc_active = 0;
MSVCRT__fmode = MSVCRT__O_TEXT;
-
- MSVCRT___initenv= msvcrt_SnapshotOfEnvironmentA(NULL);
- MSVCRT___winitenv= msvcrt_SnapshotOfEnvironmentW(NULL);
+
+ MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(NULL);
+ MSVCRT___initenv = msvcrt_SnapshotOfEnvironmentA(NULL);
+ MSVCRT___winitenv = msvcrt_SnapshotOfEnvironmentW(NULL);
MSVCRT__pgmptr = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
if (MSVCRT__pgmptr)
@@ -368,6 +365,10 @@ void CDECL __wgetmainargs(int *argc, MSVCRT_wchar_t** *wargv, MSVCRT_wchar_t** *
int expand_wildcards, int *new_mode)
{
TRACE("(%p,%p,%p,%d,%p).\n", argc, wargv, wenvp, expand_wildcards, new_mode);
+
+ /* Initialize the _wenviron array if it's not already created. */
+ if (!MSVCRT__wenviron)
+ MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(NULL);
*argc = MSVCRT___argc;
*wargv = MSVCRT___wargv;
*wenvp = MSVCRT___winitenv;
diff --git a/dlls/msvcrt/environ.c b/dlls/msvcrt/environ.c
index a60f116..6ceeebb 100644
--- a/dlls/msvcrt/environ.c
+++ b/dlls/msvcrt/environ.c
@@ -104,9 +104,8 @@ int CDECL _putenv(const char *str)
/* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */
if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0;
- /* Update the __p__environ array only when already initialized */
- if (MSVCRT__environ)
- MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(MSVCRT__environ);
+ MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(MSVCRT__environ);
+ /* Update the __p__wenviron array only when already initialized */
if (MSVCRT__wenviron)
MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(MSVCRT__wenviron);
@@ -150,11 +149,8 @@ int CDECL _wputenv(const MSVCRT_wchar_t *str)
/* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */
if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0;
- /* Update the __p__environ array only when already initialized */
- if (MSVCRT__environ)
- MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(MSVCRT__environ);
- if (MSVCRT__wenviron)
- MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(MSVCRT__wenviron);
+ MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(MSVCRT__environ);
+ MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(MSVCRT__wenviron);
finish:
HeapFree(GetProcessHeap(), 0, name);
diff --git a/dlls/msvcrt/tests/environ.c b/dlls/msvcrt/tests/environ.c
index 336238c..3169503 100644
--- a/dlls/msvcrt/tests/environ.c
+++ b/dlls/msvcrt/tests/environ.c
@@ -42,6 +42,20 @@ static const char *a_very_long_env_string =
"/usr/lib/mingw32/3.4.2/;"
"/usr/lib/";
+void __cdecl __getmainargs(int *, char ***, char ***, int, int *);
+void __cdecl __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);
+
+static char ***p_environ;
+static WCHAR ***p_wenviron;
+
+static void init(void)
+{
+ HMODULE hmod = GetModuleHandleA("msvcrt.dll");
+
+ p_environ = (void *)GetProcAddress(hmod, "_environ");
+ p_wenviron = (void *)GetProcAddress(hmod, "_wenviron");
+}
+
static void test_system(void)
{
int ret = system(NULL);
@@ -51,7 +65,112 @@ static void test_system(void)
ok(ret == 0, "Expected system to return 0, got %d\n", ret);
}
-START_TEST(environ)
+static void test__environ(void)
+{
+ int argc;
+ char **argv, **envp = NULL;
+ int i, mode = 0;
+
+ ok( p_environ != NULL, "Expected the pointer to _environ to be non-NULL\n" );
+ if (p_environ)
+ ok( *p_environ != NULL, "Expected _environ to be initialized on startup\n" );
+
+ if (!p_environ || !*p_environ)
+ {
+ skip( "_environ pointers are not valid\n" );
+ return;
+ }
+
+ /* Note that msvcrt from Windows versions older than Vista
+ * expects the mode pointer parameter to be valid.*/
+ __getmainargs(&argc, &argv, &envp, 0, &mode);
+
+ ok( envp != NULL, "Expected initial environment block pointer to be non-NULL\n" );
+ if (!envp)
+ {
+ skip( "Initial environment block pointer is not valid\n" );
+ return;
+ }
+
+ for (i = 0; ; i++)
+ {
+ if ((*p_environ)[i])
+ {
+ ok( envp[i] != NULL, "Expected environment block pointer element to be non-NULL\n" );
+ ok( !strcmp((*p_environ)[i], envp[i]),
+ "Expected _environ and environment block pointer strings (%s vs. %s) to match\n",
+ (*p_environ)[i], envp[i] );
+ }
+ else
+ {
+ ok( !envp[i], "Expected environment block pointer element to be NULL, got %p\n", envp[i] );
+ break;
+ }
+ }
+}
+
+static void test__wenviron(void)
+{
+ int argc;
+ char **argv, **envp = NULL;
+ WCHAR **wargv, **wenvp = NULL;
+ int i, mode = 0;
+
+ ok( p_wenviron != NULL, "Expected the pointer to _wenviron to be non-NULL\n" );
+ if (p_wenviron)
+ ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron );
+ else
+ {
+ skip( "Pointer to _wenviron is not valid\n" );
+ return;
+ }
+
+ /* __getmainargs doesn't initialize _wenviron. */
+ __getmainargs(&argc, &argv, &envp, 0, &mode);
+
+ ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron);
+ ok( envp != NULL, "Expected initial environment block pointer to be non-NULL\n" );
+ if (!envp)
+ {
+ skip( "Initial environment block pointer is not valid\n" );
+ return;
+ }
+
+ /* Neither does calling the non-Unicode environment manipulation functions. */
+ ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" );
+ ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron);
+ ok( _putenv("cat=") == 0, "failed deleting cat\n" );
+
+ /* _wenviron isn't initialized until __wgetmainargs is called or
+ * one of the Unicode environment manipulation functions is called. */
+ __wgetmainargs(&argc, &wargv, &wenvp, 0, &mode);
+
+ ok( *p_wenviron != NULL, "Expected _wenviron to be non-NULL\n" );
+ ok( wenvp != NULL, "Expected initial environment block pointer to be non-NULL\n" );
+ if (!wenvp)
+ {
+ skip( "Initial environment block pointer is not valid\n" );
+ return;
+ }
+
+ for (i = 0; ; i++)
+ {
+ if ((*p_wenviron)[i])
+ {
+ ok( wenvp[i] != NULL, "Expected environment block pointer element to be non-NULL\n" );
+ ok( !winetest_strcmpW((*p_wenviron)[i], wenvp[i]),
+ "Expected _wenviron and environment block pointer strings (%s vs. %s) to match\n",
+ wine_dbgstr_w((*p_wenviron)[i]), wine_dbgstr_w(wenvp[i]) );
+ }
+ else
+ {
+ ok( !wenvp[i], "Expected environment block pointer element to be NULL, got %p\n", wenvp[i] );
+ break;
+ }
+ }
+}
+
+static void test_environment_manipulation(void)
{
ok( _putenv("cat=") == 0, "_putenv failed on deletion of nonexistent environment variable\n" );
ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" );
@@ -63,6 +182,16 @@ START_TEST(environ)
ok( _putenv(a_very_long_env_string) == 0, "_putenv failed for long environment string\n");
ok( getenv("nonexistent") == NULL, "getenv should fail with nonexistent var name\n" );
+}
+
+START_TEST(environ)
+{
+ init();
+ /* The environ tests should always be run first, as they assume
+ * that the process has not manipulated the environment. */
+ test__environ();
+ test__wenviron();
+ test_environment_manipulation();
test_system();
}
More information about the wine-cvs
mailing list