2 * msvcrt.dll environment functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * 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
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
30 int env_init(BOOL unicode
, BOOL modif
)
32 if (!unicode
&& !MSVCRT___initenv
)
34 char *environ_strings
= GetEnvironmentStringsA();
35 int count
= 1, len
= 1, i
= 0; /* keep space for the trailing NULLS */
38 for (ptr
= environ_strings
; *ptr
; ptr
+= strlen(ptr
) + 1)
40 /* Don't count environment variables starting with '=' which are command shell specific */
41 if (*ptr
!= '=') count
++;
42 len
+= strlen(ptr
) + 1;
44 MSVCRT___initenv
= malloc(count
* sizeof(*MSVCRT___initenv
) + len
);
45 if (!MSVCRT___initenv
)
47 FreeEnvironmentStringsA(environ_strings
);
51 memcpy(&MSVCRT___initenv
[count
], environ_strings
, len
);
52 for (ptr
= (char *)&MSVCRT___initenv
[count
]; *ptr
; ptr
+= strlen(ptr
) + 1)
54 /* Skip special environment strings set by the command shell */
55 if (*ptr
!= '=') MSVCRT___initenv
[i
++] = ptr
;
57 MSVCRT___initenv
[i
] = NULL
;
58 FreeEnvironmentStringsA(environ_strings
);
60 MSVCRT__environ
= MSVCRT___initenv
;
63 if (!unicode
&& modif
&& MSVCRT__environ
== MSVCRT___initenv
)
67 while(MSVCRT___initenv
[i
]) i
++;
68 MSVCRT__environ
= malloc((i
+ 1) * sizeof(char *));
69 if (!MSVCRT__environ
) return -1;
70 for (i
= 0; MSVCRT___initenv
[i
]; i
++)
71 MSVCRT__environ
[i
] = strdup(MSVCRT___initenv
[i
]);
72 MSVCRT__environ
[i
] = NULL
;
75 if (unicode
&& !MSVCRT___winitenv
)
77 wchar_t *wenviron_strings
= GetEnvironmentStringsW();
78 int count
= 1, len
= 1, i
= 0; /* keep space for the trailing NULLS */
81 for (wptr
= wenviron_strings
; *wptr
; wptr
+= wcslen(wptr
) + 1)
83 /* Don't count environment variables starting with '=' which are command shell specific */
84 if (*wptr
!= '=') count
++;
85 len
+= wcslen(wptr
) + 1;
87 MSVCRT___winitenv
= malloc(count
* sizeof(*MSVCRT___winitenv
) + len
* sizeof(wchar_t));
88 if (!MSVCRT___winitenv
)
90 FreeEnvironmentStringsW(wenviron_strings
);
94 memcpy(&MSVCRT___winitenv
[count
], wenviron_strings
, len
* sizeof(wchar_t));
95 for (wptr
= (wchar_t *)&MSVCRT___winitenv
[count
]; *wptr
; wptr
+= wcslen(wptr
) + 1)
97 /* Skip special environment strings set by the command shell */
98 if (*wptr
!= '=') MSVCRT___winitenv
[i
++] = wptr
;
100 MSVCRT___winitenv
[i
] = NULL
;
101 FreeEnvironmentStringsW(wenviron_strings
);
103 MSVCRT__wenviron
= MSVCRT___winitenv
;
106 if (unicode
&& modif
&& MSVCRT__wenviron
== MSVCRT___winitenv
)
110 while(MSVCRT___winitenv
[i
]) i
++;
111 MSVCRT__wenviron
= malloc((i
+ 1) * sizeof(wchar_t *));
112 if (!MSVCRT__wenviron
) return -1;
113 for (i
= 0; MSVCRT___winitenv
[i
]; i
++)
114 MSVCRT__wenviron
[i
] = wcsdup(MSVCRT___winitenv
[i
]);
115 MSVCRT__wenviron
[i
] = NULL
;
121 static int env_get_index(const char *name
)
126 for (i
= 0; MSVCRT__environ
[i
]; i
++)
128 if (!strncmp(name
, MSVCRT__environ
[i
], len
) && MSVCRT__environ
[i
][len
] == '=')
134 static int wenv_get_index(const wchar_t *name
)
139 for (i
= 0; MSVCRT__wenviron
[i
]; i
++)
141 if (!wcsncmp(name
, MSVCRT__wenviron
[i
], len
) && MSVCRT__wenviron
[i
][len
] == '=')
147 static int env_set(char **env
, wchar_t **wenv
)
149 wchar_t *weq
= wcschr(*wenv
, '=');
150 char *eq
= strchr(*env
, '=');
154 if (!SetEnvironmentVariableW(*wenv
, weq
[1] ? weq
+ 1 : NULL
) &&
155 GetLastError() != ERROR_ENVVAR_NOT_FOUND
)
159 idx
= env_get_index(*env
);
163 for(; MSVCRT__environ
[idx
]; idx
++)
164 MSVCRT__environ
[idx
] = MSVCRT__environ
[idx
+ 1];
166 else if (MSVCRT__environ
[idx
])
168 free(MSVCRT__environ
[idx
]);
169 MSVCRT__environ
[idx
] = *env
;
174 char **new_env
= realloc(MSVCRT__environ
, (idx
+ 2) * sizeof(*MSVCRT__environ
));
175 if (!new_env
) return -1;
176 MSVCRT__environ
= new_env
;
177 MSVCRT__environ
[idx
] = *env
;
178 MSVCRT__environ
[idx
+ 1] = NULL
;
182 if (!MSVCRT__wenviron
) return 0;
183 idx
= wenv_get_index(*wenv
);
187 for(; MSVCRT__wenviron
[idx
]; idx
++)
188 MSVCRT__wenviron
[idx
] = MSVCRT__wenviron
[idx
+ 1];
190 else if (MSVCRT__wenviron
[idx
])
192 free(MSVCRT__wenviron
[idx
]);
193 MSVCRT__wenviron
[idx
] = *wenv
;
198 wchar_t **new_env
= realloc(MSVCRT__wenviron
, (idx
+ 2) * sizeof(*MSVCRT__wenviron
));
199 if (!new_env
) return -1;
200 MSVCRT__wenviron
= new_env
;
201 MSVCRT__wenviron
[idx
] = *wenv
;
202 MSVCRT__wenviron
[idx
+ 1] = NULL
;
208 static char * getenv_helper(const char *name
)
212 if (!name
) return NULL
;
214 idx
= env_get_index(name
);
215 if (!MSVCRT__environ
[idx
]) return NULL
;
216 return strchr(MSVCRT__environ
[idx
], '=') + 1;
219 /*********************************************************************
222 char * CDECL
getenv(const char *name
)
226 if (!MSVCRT_CHECK_PMT(name
!= NULL
)) return NULL
;
229 ret
= getenv_helper(name
);
234 static wchar_t * wgetenv_helper(const wchar_t *name
)
238 if (!name
) return NULL
;
239 if (env_init(TRUE
, FALSE
)) return NULL
;
241 idx
= wenv_get_index(name
);
242 if (!MSVCRT__wenviron
[idx
]) return NULL
;
243 return wcschr(MSVCRT__wenviron
[idx
], '=') + 1;
246 /*********************************************************************
247 * _wgetenv (MSVCRT.@)
249 wchar_t * CDECL
_wgetenv(const wchar_t *name
)
253 if (!MSVCRT_CHECK_PMT(name
!= NULL
)) return NULL
;
256 ret
= wgetenv_helper(name
);
261 static int putenv_helper(const char *name
, const char *val
, const char *eq
)
268 r
= env_init(FALSE
, TRUE
);
279 int name_len
= strlen(name
);
282 env
= malloc(name_len
+ r
+ 2);
284 memcpy(env
, name
, name_len
);
286 strcpy(env
+ name_len
+ 1, val
);
289 wenv
= msvcrt_wstrdupa(env
);
297 r
= env_set(&env
, &wenv
);
304 static char *msvcrt_astrdupw(const wchar_t *wstr
)
306 const unsigned int len
= WideCharToMultiByte(CP_ACP
, 0, wstr
, -1, NULL
, 0, NULL
, NULL
);
307 char *str
= malloc(len
* sizeof(char));
311 WideCharToMultiByte(CP_ACP
, 0, wstr
, -1, str
, len
, NULL
, NULL
);
316 static int wputenv_helper(const wchar_t *name
, const wchar_t *val
, const wchar_t *eq
)
323 r
= env_init(TRUE
, TRUE
);
330 if (!wenv
) return -1;
334 int name_len
= wcslen(name
);
337 wenv
= malloc((name_len
+ r
+ 2) * sizeof(wchar_t));
338 if (!wenv
) return -1;
339 memcpy(wenv
, name
, name_len
* sizeof(wchar_t));
340 wenv
[name_len
] = '=';
341 wcscpy(wenv
+ name_len
+ 1, val
);
344 env
= msvcrt_astrdupw(wenv
);
352 r
= env_set(&env
, &wenv
);
359 /*********************************************************************
362 int CDECL
_putenv(const char *str
)
366 TRACE("%s\n", debugstr_a(str
));
368 if (!str
|| !(eq
= strchr(str
, '=')))
371 return putenv_helper(str
, NULL
, eq
);
374 /*********************************************************************
375 * _wputenv (MSVCRT.@)
377 int CDECL
_wputenv(const wchar_t *str
)
381 TRACE("%s\n", debugstr_w(str
));
383 if (!str
|| !(eq
= wcschr(str
, '=')))
386 return wputenv_helper(str
, NULL
, eq
);
389 /*********************************************************************
390 * _putenv_s (MSVCRT.@)
392 errno_t CDECL
_putenv_s(const char *name
, const char *value
)
396 TRACE("%s %s\n", debugstr_a(name
), debugstr_a(value
));
398 if (!MSVCRT_CHECK_PMT(name
!= NULL
)) return EINVAL
;
399 if (!MSVCRT_CHECK_PMT(value
!= NULL
)) return EINVAL
;
401 if (putenv_helper(name
, value
, NULL
) < 0)
403 msvcrt_set_errno(GetLastError());
410 /*********************************************************************
411 * _wputenv_s (MSVCRT.@)
413 errno_t CDECL
_wputenv_s(const wchar_t *name
, const wchar_t *value
)
417 TRACE("%s %s\n", debugstr_w(name
), debugstr_w(value
));
419 if (!MSVCRT_CHECK_PMT(name
!= NULL
)) return EINVAL
;
420 if (!MSVCRT_CHECK_PMT(value
!= NULL
)) return EINVAL
;
422 if (wputenv_helper(name
, value
, NULL
) < 0)
424 msvcrt_set_errno(GetLastError());
433 /******************************************************************
434 * _dupenv_s (MSVCR80.@)
436 int CDECL
_dupenv_s(char **buffer
, size_t *numberOfElements
, const char *varname
)
441 if (!MSVCRT_CHECK_PMT(buffer
!= NULL
)) return EINVAL
;
442 if (!MSVCRT_CHECK_PMT(varname
!= NULL
)) return EINVAL
;
445 if (!(e
= getenv(varname
)))
449 if (numberOfElements
) *numberOfElements
= 0;
454 *buffer
= malloc(sz
);
455 if (*buffer
) strcpy(*buffer
, e
);
460 if (numberOfElements
) *numberOfElements
= 0;
461 return *_errno() = ENOMEM
;
463 if (numberOfElements
) *numberOfElements
= sz
;
467 /******************************************************************
468 * _wdupenv_s (MSVCR80.@)
470 int CDECL
_wdupenv_s(wchar_t **buffer
, size_t *numberOfElements
,
471 const wchar_t *varname
)
476 if (!MSVCRT_CHECK_PMT(buffer
!= NULL
)) return EINVAL
;
477 if (!MSVCRT_CHECK_PMT(varname
!= NULL
)) return EINVAL
;
480 if (!(e
= _wgetenv(varname
)))
484 if (numberOfElements
) *numberOfElements
= 0;
489 *buffer
= malloc(sz
* sizeof(wchar_t));
490 if (*buffer
) wcscpy(*buffer
, e
);
495 if (numberOfElements
) *numberOfElements
= 0;
496 return *_errno() = ENOMEM
;
498 if (numberOfElements
) *numberOfElements
= sz
;
502 #endif /* _MSVCR_VER>=80 */
504 /******************************************************************
505 * getenv_s (MSVCRT.@)
507 int CDECL
getenv_s(size_t *ret_len
, char* buffer
, size_t len
, const char *varname
)
511 if (!MSVCRT_CHECK_PMT(ret_len
!= NULL
)) return EINVAL
;
513 if (!MSVCRT_CHECK_PMT((buffer
&& len
> 0) || (!buffer
&& !len
))) return EINVAL
;
514 if (buffer
) buffer
[0] = 0;
517 e
= getenv_helper(varname
);
520 *ret_len
= strlen(e
) + 1;
521 if (len
>= *ret_len
) strcpy(buffer
, e
);
525 if (!e
|| !len
) return 0;
526 if (len
< *ret_len
) return ERANGE
;
530 /******************************************************************
531 * _wgetenv_s (MSVCRT.@)
533 int CDECL
_wgetenv_s(size_t *ret_len
, wchar_t *buffer
, size_t len
,
534 const wchar_t *varname
)
538 if (!MSVCRT_CHECK_PMT(ret_len
!= NULL
)) return EINVAL
;
540 if (!MSVCRT_CHECK_PMT((buffer
&& len
> 0) || (!buffer
&& !len
))) return EINVAL
;
541 if (buffer
) buffer
[0] = 0;
544 e
= wgetenv_helper(varname
);
547 *ret_len
= wcslen(e
) + 1;
548 if (len
>= *ret_len
) wcscpy(buffer
, e
);
552 if (!e
|| !len
) return 0;
553 if (len
< *ret_len
) return ERANGE
;
557 /*********************************************************************
558 * _get_environ (MSVCRT.@)
560 void CDECL
_get_environ(char ***ptr
)
562 *ptr
= MSVCRT__environ
;
565 /*********************************************************************
566 * _get_wenviron (MSVCRT.@)
568 void CDECL
_get_wenviron(wchar_t ***ptr
)
570 *ptr
= MSVCRT__wenviron
;