environ.c 8.88 KB
Newer Older
1 2 3 4 5 6 7
/*
 * msvcrt.dll environment functions
 *
 * Copyright 1996,1998 Marcus Meissner
 * Copyright 1996 Jukka Iivonen
 * Copyright 1997,2000 Uwe Bonnes
 * Copyright 2000 Jon Griffiths
8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * 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
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 23 24
 */
#include "wine/unicode.h"
#include "msvcrt.h"
25 26 27
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
28 29 30 31

/*********************************************************************
 *		getenv (MSVCRT.@)
 */
32
char * CDECL MSVCRT_getenv(const char *name)
33
{
34 35
    char **environ;
    unsigned int length=strlen(name);
36

37
    for (environ = MSVCRT__environ; *environ; environ++)
38 39 40 41 42 43 44 45 46 47
    {
        char *str = *environ;
        char *pos = strchr(str,'=');
        if (pos && ((pos - str) == length) && !strncasecmp(str,name,length))
        {
            TRACE("(%s): got %s\n", debugstr_a(name), debugstr_a(pos + 1));
            return pos + 1;
        }
    }
    return NULL;
48 49 50 51 52
}

/*********************************************************************
 *		_wgetenv (MSVCRT.@)
 */
53
MSVCRT_wchar_t * CDECL MSVCRT__wgetenv(const MSVCRT_wchar_t *name)
54
{
55 56
    MSVCRT_wchar_t **environ;
    unsigned int length=strlenW(name);
57

58 59 60 61 62
    /* Initialize the _wenviron array if it's not already created. */
    if (!MSVCRT__wenviron)
        MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(NULL);

    for (environ = MSVCRT__wenviron; *environ; environ++)
63 64 65 66 67 68 69 70 71 72
    {
        MSVCRT_wchar_t *str = *environ;
        MSVCRT_wchar_t *pos = strchrW(str,'=');
        if (pos && ((pos - str) == length) && !strncmpiW(str,name,length))
        {
            TRACE("(%s): got %s\n", debugstr_w(name), debugstr_w(pos + 1));
            return pos + 1;
        }
    }
    return NULL;
73
}
74 75 76 77

/*********************************************************************
 *		_putenv (MSVCRT.@)
 */
78
int CDECL _putenv(const char *str)
79
{
80 81
 char *name, *value;
 char *dst;
82
 int ret;
83

84
 TRACE("%s\n", debugstr_a(str));
85 86 87

 if (!str)
   return -1;
88 89 90 91 92
   
 name = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
 if (!name)
   return -1;
 dst = name;
93 94 95
 while (*str && *str != '=')
  *dst++ = *str++;
 if (!*str++)
96 97 98 99 100 101
 {
   ret = -1;
   goto finish;
 }
 *dst++ = '\0';
 value = dst;
102 103 104 105
 while (*str)
  *dst++ = *str++;
 *dst = '\0';

106 107
 ret = SetEnvironmentVariableA(name, value[0] ? value : NULL) ? 0 : -1;

108
 /* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */
109 110
 if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0;

111 112
 MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(MSVCRT__environ);
 /* Update the __p__wenviron array only when already initialized */
113 114
 if (MSVCRT__wenviron)
   MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(MSVCRT__wenviron);
115 116 117
   
finish:
 HeapFree(GetProcessHeap(), 0, name);
118
 return ret;
119 120 121 122 123
}

/*********************************************************************
 *		_wputenv (MSVCRT.@)
 */
124
int CDECL _wputenv(const MSVCRT_wchar_t *str)
125
{
126 127
 MSVCRT_wchar_t *name, *value;
 MSVCRT_wchar_t *dst;
128
 int ret;
129 130 131 132 133

 TRACE("%s\n", debugstr_w(str));

 if (!str)
   return -1;
134 135 136 137
 name = HeapAlloc(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(MSVCRT_wchar_t));
 if (!name)
   return -1;
 dst = name;
138
 while (*str && *str != '=')
139 140
  *dst++ = *str++;
 if (!*str++)
141 142 143 144 145 146
 {
   ret = -1;
   goto finish;
 }
 *dst++ = 0;
 value = dst;
147 148
 while (*str)
  *dst++ = *str++;
149
 *dst = 0;
150

151 152
 ret = SetEnvironmentVariableW(name, value[0] ? value : NULL) ? 0 : -1;

153
 /* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */
154 155
 if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0;

156 157
 MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(MSVCRT__environ);
 MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(MSVCRT__wenviron);
158 159 160

finish:
 HeapFree(GetProcessHeap(), 0, name);
161
 return ret;
162
}
163 164 165 166 167 168 169 170 171 172

/*********************************************************************
 *		_putenv_s (MSVCRT.@)
 */
int CDECL _putenv_s(const char *name, const char *value)
{
    int ret;

    TRACE("%s %s\n", debugstr_a(name), debugstr_a(value));

173 174
    if (!MSVCRT_CHECK_PMT(name != NULL)) return -1;
    if (!MSVCRT_CHECK_PMT(value != NULL)) return -1;
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195

    ret = SetEnvironmentVariableA(name, value[0] ? value : NULL) ? 0 : -1;

    /* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */
    if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0;

    MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(MSVCRT__environ);
    MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(MSVCRT__wenviron);

    return ret;
}

/*********************************************************************
 *		_wputenv_s (MSVCRT.@)
 */
int CDECL _wputenv_s(const MSVCRT_wchar_t *name, const MSVCRT_wchar_t *value)
{
    int ret;

    TRACE("%s %s\n", debugstr_w(name), debugstr_w(value));

196 197
    if (!MSVCRT_CHECK_PMT(name != NULL)) return -1;
    if (!MSVCRT_CHECK_PMT(value != NULL)) return -1;
198 199 200 201 202 203 204 205 206 207 208

    ret = SetEnvironmentVariableW(name, value[0] ? value : NULL) ? 0 : -1;

    /* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */
    if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0;

    MSVCRT__environ = msvcrt_SnapshotOfEnvironmentA(MSVCRT__environ);
    MSVCRT__wenviron = msvcrt_SnapshotOfEnvironmentW(MSVCRT__wenviron);

    return ret;
}
209 210 211 212

/******************************************************************
 *		_dupenv_s (MSVCRT.@)
 */
213
int CDECL _dupenv_s(char **buffer, MSVCRT_size_t *numberOfElements, const char *varname)
214 215 216 217
{
    char*               e;
    MSVCRT_size_t       sz;

218 219 220 221 222
    if (!MSVCRT_CHECK_PMT(buffer != NULL)) return MSVCRT_EINVAL;
    if (!MSVCRT_CHECK_PMT(varname != NULL)) return MSVCRT_EINVAL;

    if (!(e = MSVCRT_getenv(varname))) return *MSVCRT__errno() = MSVCRT_EINVAL;

223 224 225 226 227 228 229 230 231 232 233 234 235 236
    sz = strlen(e) + 1;
    if (!(*buffer = MSVCRT_malloc(sz)))
    {
        if (numberOfElements) *numberOfElements = 0;
        return *MSVCRT__errno() = MSVCRT_ENOMEM;
    }
    strcpy(*buffer, e);
    if (numberOfElements) *numberOfElements = sz;
    return 0;
}

/******************************************************************
 *		_wdupenv_s (MSVCRT.@)
 */
237 238
int CDECL _wdupenv_s(MSVCRT_wchar_t **buffer, MSVCRT_size_t *numberOfElements,
                     const MSVCRT_wchar_t *varname)
239 240 241 242
{
    MSVCRT_wchar_t*     e;
    MSVCRT_size_t       sz;

243 244 245 246 247
    if (!MSVCRT_CHECK_PMT(buffer != NULL)) return MSVCRT_EINVAL;
    if (!MSVCRT_CHECK_PMT(varname != NULL)) return MSVCRT_EINVAL;

    if (!(e = MSVCRT__wgetenv(varname))) return *MSVCRT__errno() = MSVCRT_EINVAL;

248 249 250 251 252 253 254 255 256 257
    sz = strlenW(e) + 1;
    if (!(*buffer = MSVCRT_malloc(sz * sizeof(MSVCRT_wchar_t))))
    {
        if (numberOfElements) *numberOfElements = 0;
        return *MSVCRT__errno() = MSVCRT_ENOMEM;
    }
    strcpyW(*buffer, e);
    if (numberOfElements) *numberOfElements = sz;
    return 0;
}
258 259 260 261

/******************************************************************
 *		getenv_s (MSVCRT.@)
 */
262
int CDECL getenv_s(MSVCRT_size_t *pReturnValue, char* buffer, MSVCRT_size_t numberOfElements, const char *varname)
263 264 265
{
    char*       e;

266 267 268 269
    if (!MSVCRT_CHECK_PMT(pReturnValue != NULL)) return MSVCRT_EINVAL;
    if (!MSVCRT_CHECK_PMT(!(buffer == NULL && numberOfElements > 0))) return MSVCRT_EINVAL;
    if (!MSVCRT_CHECK_PMT(varname != NULL)) return MSVCRT_EINVAL;

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
    if (!(e = MSVCRT_getenv(varname)))
    {
        *pReturnValue = 0;
        return *MSVCRT__errno() = MSVCRT_EINVAL;
    }
    *pReturnValue = strlen(e) + 1;
    if (numberOfElements < *pReturnValue)
    {
        return *MSVCRT__errno() = MSVCRT_ERANGE;
    }
    strcpy(buffer, e);
    return 0;
}

/******************************************************************
 *		_wgetenv_s (MSVCRT.@)
 */
287 288
int CDECL _wgetenv_s(MSVCRT_size_t *pReturnValue, MSVCRT_wchar_t *buffer, MSVCRT_size_t numberOfElements,
                     const MSVCRT_wchar_t *varname)
289 290 291
{
    MSVCRT_wchar_t*     e;

292 293 294 295
    if (!MSVCRT_CHECK_PMT(pReturnValue != NULL)) return MSVCRT_EINVAL;
    if (!MSVCRT_CHECK_PMT(!(buffer == NULL && numberOfElements > 0))) return MSVCRT_EINVAL;
    if (!MSVCRT_CHECK_PMT(varname != NULL)) return MSVCRT_EINVAL;

296
    if (!(e = MSVCRT__wgetenv(varname)))
297 298 299 300 301 302 303 304 305 306 307 308
    {
        *pReturnValue = 0;
        return *MSVCRT__errno() = MSVCRT_EINVAL;
    }
    *pReturnValue = strlenW(e) + 1;
    if (numberOfElements < *pReturnValue)
    {
        return *MSVCRT__errno() = MSVCRT_ERANGE;
    }
    strcpyW(buffer, e);
    return 0;
}