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