|  | /* | 
|  | * Unit test suite for userenv functions | 
|  | * | 
|  | * Copyright 2008 Google (Lei Zhang) | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <stdarg.h> | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "winnls.h" | 
|  |  | 
|  | #include "userenv.h" | 
|  |  | 
|  | #include "wine/test.h" | 
|  |  | 
|  | #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT)) | 
|  | #define expect_env(EXPECTED,GOT,VAR) ok((GOT)==(EXPECTED), "Expected %d, got %d for %s (%d)\n", (EXPECTED), (GOT), (VAR), j) | 
|  |  | 
|  | struct profile_item | 
|  | { | 
|  | const char * name; | 
|  | const int todo[4]; | 
|  | }; | 
|  |  | 
|  | /* Debugging functions from wine/libs/wine/debug.c, slightly modified */ | 
|  |  | 
|  | /* allocate some tmp string space */ | 
|  | /* FIXME: this is not 100% thread-safe */ | 
|  | static char *get_tmp_space( int size ) | 
|  | { | 
|  | static char *list[32]; | 
|  | static long pos; | 
|  | char *ret; | 
|  | int idx; | 
|  |  | 
|  | idx = ++pos % (sizeof(list)/sizeof(list[0])); | 
|  | if ((ret = realloc( list[idx], size ))) list[idx] = ret; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* default implementation of wine_dbgstr_wn */ | 
|  | static const char *default_dbgstr_wn( const WCHAR *str, int n, BOOL quotes ) | 
|  | { | 
|  | char *dst, *res; | 
|  |  | 
|  | if (!HIWORD(str)) | 
|  | { | 
|  | if (!str) return "(null)"; | 
|  | res = get_tmp_space( 6 ); | 
|  | sprintf( res, "#%04x", LOWORD(str) ); | 
|  | return res; | 
|  | } | 
|  | if (n == -1) n = lstrlenW(str); | 
|  | if (n < 0) n = 0; | 
|  | else if (n > 200) n = 200; | 
|  | dst = res = get_tmp_space( n * 5 + 7 ); | 
|  | if (quotes) | 
|  | { | 
|  | *dst++ = 'L'; | 
|  | *dst++ = '"'; | 
|  | } | 
|  | while (n-- > 0) | 
|  | { | 
|  | WCHAR c = *str++; | 
|  | switch (c) | 
|  | { | 
|  | case '\n': *dst++ = '\\'; *dst++ = 'n'; break; | 
|  | case '\r': *dst++ = '\\'; *dst++ = 'r'; break; | 
|  | case '\t': *dst++ = '\\'; *dst++ = 't'; break; | 
|  | case '"':  *dst++ = '\\'; *dst++ = '"'; break; | 
|  | case '\\': *dst++ = '\\'; *dst++ = '\\'; break; | 
|  | default: | 
|  | if (c >= ' ' && c <= 126) | 
|  | *dst++ = (char)c; | 
|  | else | 
|  | { | 
|  | *dst++ = '\\'; | 
|  | sprintf(dst,"%04x",c); | 
|  | dst+=4; | 
|  | } | 
|  | } | 
|  | } | 
|  | if (quotes) *dst++ = '"'; | 
|  | if (*str) | 
|  | { | 
|  | *dst++ = '.'; | 
|  | *dst++ = '.'; | 
|  | *dst++ = '.'; | 
|  | } | 
|  | *dst = 0; | 
|  | return res; | 
|  | } | 
|  |  | 
|  | const char *wine_dbgstr_wn( const WCHAR *s, int n ) | 
|  | { | 
|  | return default_dbgstr_wn(s, n, TRUE); | 
|  | } | 
|  |  | 
|  | const char *wine_dbgstr_w( const WCHAR *s ) | 
|  | { | 
|  | return default_dbgstr_wn( s, -1, TRUE); | 
|  | } | 
|  |  | 
|  | static const char *userenv_dbgstr_w( const WCHAR *s ) | 
|  | { | 
|  | return default_dbgstr_wn( s, -1, FALSE); | 
|  | } | 
|  |  | 
|  | /* Helper function for retrieving environment variables */ | 
|  | static BOOL get_env(const WCHAR * env, const char * var, char ** result) | 
|  | { | 
|  | const WCHAR * p = env; | 
|  | int envlen, varlen, buflen; | 
|  | char buf[256]; | 
|  |  | 
|  | if (!env || !var || !result) return FALSE; | 
|  |  | 
|  | varlen = strlen(var); | 
|  | do | 
|  | { | 
|  | envlen = lstrlenW(p); | 
|  | sprintf(buf, "%s", userenv_dbgstr_w(p)); | 
|  | if (CompareStringA(GetThreadLocale(), NORM_IGNORECASE|LOCALE_USE_CP_ACP, buf, min(envlen, varlen), var, varlen) == CSTR_EQUAL) | 
|  | { | 
|  | if (buf[varlen] == '=') | 
|  | { | 
|  | buflen = strlen(buf); | 
|  | *result = HeapAlloc(GetProcessHeap(), 0, buflen + 1); | 
|  | if (!*result) return FALSE; | 
|  | memcpy(*result, buf, buflen + 1); | 
|  | return TRUE; | 
|  | } | 
|  | } | 
|  | p = p + envlen + 1; | 
|  | } while (*p); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | static void test_create_env(void) | 
|  | { | 
|  | BOOL r; | 
|  | HANDLE htok; | 
|  | WCHAR * env[4]; | 
|  | char * st; | 
|  | int i, j; | 
|  |  | 
|  | static const struct profile_item common_vars[] = { | 
|  | { "ComSpec", { 1, 1, 0, 0 } }, | 
|  | { "COMPUTERNAME", { 1, 1, 1, 1 } }, | 
|  | { "NUMBER_OF_PROCESSORS", { 1, 1, 0, 0 } }, | 
|  | { "OS", { 1, 1, 0, 0 } }, | 
|  | { "PROCESSOR_ARCHITECTURE", { 1, 1, 0, 0 } }, | 
|  | { "PROCESSOR_IDENTIFIER", { 1, 1, 0, 0 } }, | 
|  | { "PROCESSOR_LEVEL", { 1, 1, 0, 0 } }, | 
|  | { "PROCESSOR_REVISION", { 1, 1, 0, 0 } }, | 
|  | { "SystemDrive", { 1, 1, 0, 0 } }, | 
|  | { "SystemRoot", { 1, 1, 0, 0 } }, | 
|  | { "windir", { 1, 1, 0, 0 } } | 
|  | }; | 
|  | static const struct profile_item common_post_nt4_vars[] = { | 
|  | { "ALLUSERSPROFILE", { 1, 1, 0, 0 } }, | 
|  | { "TEMP", { 1, 1, 0, 0 } }, | 
|  | { "TMP", { 1, 1, 0, 0 } }, | 
|  | { "CommonProgramFiles", { 1, 1, 1, 1 } }, | 
|  | { "ProgramFiles", { 1, 1, 0, 0 } } | 
|  | }; | 
|  | static const struct profile_item htok_vars[] = { | 
|  | { "PATH", { 1, 1, 0, 0 } }, | 
|  | { "USERPROFILE", { 1, 1, 0, 0 } } | 
|  | }; | 
|  |  | 
|  | r = SetEnvironmentVariableA("WINE_XYZZY", "ZZYZX"); | 
|  | expect(TRUE, r); | 
|  |  | 
|  | if (0) | 
|  | { | 
|  | /* Crashes on NT4 */ | 
|  | r = CreateEnvironmentBlock(NULL, NULL, FALSE); | 
|  | expect(FALSE, r); | 
|  | } | 
|  |  | 
|  | r = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &htok); | 
|  | expect(TRUE, r); | 
|  |  | 
|  | if (0) | 
|  | { | 
|  | /* Crashes on NT4 */ | 
|  | r = CreateEnvironmentBlock(NULL, htok, FALSE); | 
|  | expect(FALSE, r); | 
|  | } | 
|  |  | 
|  | r = CreateEnvironmentBlock((LPVOID) &env[0], NULL, FALSE); | 
|  | expect(TRUE, r); | 
|  |  | 
|  | r = CreateEnvironmentBlock((LPVOID) &env[1], htok, FALSE); | 
|  | expect(TRUE, r); | 
|  |  | 
|  | r = CreateEnvironmentBlock((LPVOID) &env[2], NULL, TRUE); | 
|  | expect(TRUE, r); | 
|  |  | 
|  | r = CreateEnvironmentBlock((LPVOID) &env[3], htok, TRUE); | 
|  | expect(TRUE, r); | 
|  |  | 
|  | /* Test for common environment variables (NT4 and higher) */ | 
|  | for (i = 0; i < sizeof(common_vars)/sizeof(common_vars[0]); i++) | 
|  | { | 
|  | for (j = 0; j < 4; j++) | 
|  | { | 
|  | r = get_env(env[j], common_vars[i].name, &st); | 
|  | if (common_vars[i].todo[j]) | 
|  | todo_wine expect_env(TRUE, r, common_vars[i].name); | 
|  | else | 
|  | expect_env(TRUE, r, common_vars[i].name); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Test for common environment variables (post NT4) */ | 
|  | if (!GetEnvironmentVariableA("ALLUSERSPROFILE", NULL, 0)) | 
|  | { | 
|  | win_skip("Some environment variables are not present on NT4\n"); | 
|  | } | 
|  | else | 
|  | { | 
|  | for (i = 0; i < sizeof(common_post_nt4_vars)/sizeof(common_post_nt4_vars[0]); i++) | 
|  | { | 
|  | for (j = 0; j < 4; j++) | 
|  | { | 
|  | r = get_env(env[j], common_post_nt4_vars[i].name, &st); | 
|  | if (common_post_nt4_vars[i].todo[j]) | 
|  | todo_wine expect_env(TRUE, r, common_post_nt4_vars[i].name); | 
|  | else | 
|  | expect_env(TRUE, r, common_post_nt4_vars[i].name); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Test for environment variables with values that depends on htok */ | 
|  | for (i = 0; i < sizeof(htok_vars)/sizeof(htok_vars[0]); i++) | 
|  | { | 
|  | for (j = 0; j < 4; j++) | 
|  | { | 
|  | r = get_env(env[j], htok_vars[i].name, &st); | 
|  | if (htok_vars[i].todo[j]) | 
|  | todo_wine expect_env(TRUE, r, htok_vars[i].name); | 
|  | else | 
|  | expect_env(TRUE, r, htok_vars[i].name); | 
|  | } | 
|  | } | 
|  |  | 
|  | r = get_env(env[0], "WINE_XYZZY", &st); | 
|  | expect(FALSE, r); | 
|  | r = get_env(env[1], "WINE_XYZZY", &st); | 
|  | expect(FALSE, r); | 
|  | r = get_env(env[2], "WINE_XYZZY", &st); | 
|  | expect(TRUE, r); | 
|  | r = get_env(env[3], "WINE_XYZZY", &st); | 
|  | expect(TRUE, r); | 
|  | } | 
|  |  | 
|  | START_TEST(userenv) | 
|  | { | 
|  | test_create_env(); | 
|  | } |