ReactOS 0.4.15-dev-7842-g558ab78
putenv.c File Reference
#include <precomp.h>
Include dependency graph for putenv.c:

Go to the source code of this file.

Functions

int SetEnv (const wchar_t *option)
 
int _putenv (const char *val)
 

Function Documentation

◆ _putenv()

int _putenv ( const char val)

Definition at line 18 of file putenv.c.

19{
20 int size, result;
21 wchar_t *woption;
22
23 size = MultiByteToWideChar(CP_ACP, 0, val, -1, NULL, 0);
24 woption = malloc(size* sizeof(wchar_t));
25 if (woption == NULL)
26 return -1;
27 MultiByteToWideChar(CP_ACP, 0, val, -1, woption, size);
28 result = SetEnv(woption);
29 free(woption);
30 return result;
31}
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define CP_ACP
Definition: compat.h:109
#define MultiByteToWideChar
Definition: compat.h:110
GLsizeiptr size
Definition: glext.h:5919
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
int SetEnv(const wchar_t *option)
Definition: environ.c:210

◆ SetEnv()

int SetEnv ( const wchar_t option)

Internal version of _wputenv and _putenv. It works duplicates the original envirnments created during initilization if needed to prevent having spurious pointers floating around. Then it updates the internal environment tables (_environ and _wenviron) and at last updates the OS environemnt.

Note that there can happen situation when the internal [_w]environ arrays will be updated, but the OS environment update will fail. In this case we don't undo the changes to the [_w]environ tables to comply with the Microsoft behaviour (and it's also much easier :-).

Definition at line 210 of file environ.c.

211{
212 wchar_t *epos, *name;
213 wchar_t **wenvptr;
214 wchar_t *woption;
215 char *mboption;
216 int remove, index, count, size, result = 0, found = 0;
217 wchar_t **wnewenv;
218 char **mbnewenv;
219
220 if (option == NULL || (epos = wcschr(option, L'=')) == NULL)
221 return -1;
222 remove = (epos[1] == 0);
223
224 /* Duplicate environment if needed. */
225 if (_environ == __initenv)
226 {
228 return -1;
229 }
230 if (_wenviron == __winitenv)
231 {
232 if ((_wenviron = (wchar_t**)DuplicateEnvironment((char**)_wenviron, 1)) ==
234 return -1;
235 }
236
237 /* Create a copy of the option name. */
238 name = malloc((epos - option + 1) * sizeof(wchar_t));
239 if (name == NULL)
240 return -1;
241 memcpy(name, option, (epos - option) * sizeof(wchar_t));
242 name[epos - option] = 0;
243
244 /* Find the option we're trying to modify. */
245 for (index = 0, wenvptr = _wenviron; *wenvptr != NULL; wenvptr++, index++)
246 {
247 if (!_wcsnicmp(*wenvptr, option, epos - option))
248 {
249 found = 1;
250 break;
251 }
252 }
253
254 if (remove)
255 {
256 if (!found)
257 {
258 free(name);
259 return 0;
260 }
261
262 /* Remove the option from wide character environment. */
263 free(*wenvptr);
264 for (count = index; *wenvptr != NULL; wenvptr++, count++)
265 *wenvptr = *(wenvptr + 1);
266 wnewenv = realloc(_wenviron, count * sizeof(wchar_t*));
267 if (wnewenv != NULL)
268 _wenviron = wnewenv;
269
270 /* Remove the option from multibyte environment. We assume
271 * the environments are in sync and the option is at the
272 * same position. */
274 memmove(&_environ[index], &_environ[index+1], (count - index) * sizeof(char*));
275 mbnewenv = realloc(_environ, count * sizeof(char*));
276 if (mbnewenv != NULL)
277 _environ = mbnewenv;
278
280 }
281 else
282 {
283 /* Make a copy of the option that we will store in the environment block. */
284 woption = _wcsdup((wchar_t*)option);
285 if (woption == NULL)
286 {
287 free(name);
288 return -1;
289 }
290
291 /* Create a multibyte copy of the option. */
293 mboption = malloc(size);
294 if (mboption == NULL)
295 {
296 free(name);
297 free(woption);
298 return -1;
299 }
300 WideCharToMultiByte(CP_ACP, 0, option, -1, mboption, size, NULL, NULL);
301
302 if (found)
303 {
304 /* Replace the current entry. */
305 free(*wenvptr);
306 *wenvptr = woption;
308 _environ[index] = mboption;
309 }
310 else
311 {
312 /* Get the size of the original environment. */
313 for (count = index; *wenvptr != NULL; wenvptr++, count++)
314 ;
315
316 /* Create a new entry. */
317 if ((wnewenv = realloc(_wenviron, (count + 2) * sizeof(wchar_t*))) == NULL)
318 {
319 free(name);
320 free(mboption);
321 free(woption);
322 return -1;
323 }
324 _wenviron = wnewenv;
325 if ((mbnewenv = realloc(_environ, (count + 2) * sizeof(char*))) == NULL)
326 {
327 free(name);
328 free(mboption);
329 free(woption);
330 return -1;
331 }
332 _environ = mbnewenv;
333
334 /* Set the last entry to our option. */
335 _wenviron[count] = woption;
336 _environ[count] = mboption;
337 _wenviron[count + 1] = NULL;
338 _environ[count + 1] = NULL;
339 }
340
341 /* And finally update the OS environment. */
342 result = SetEnvironmentVariableW(name, epos + 1) ? 0 : -1;
343 }
344 free(name);
345
346 return result;
347}
#define index(s, c)
Definition: various.h:29
#define realloc
Definition: debug_ros.c:6
#define wcschr
Definition: compat.h:17
#define WideCharToMultiByte
Definition: compat.h:111
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW(IN LPCWSTR lpName, IN LPCWSTR lpValue)
Definition: environ.c:259
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint index
Definition: glext.h:6031
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
int remove
Definition: msacm.c:1366
#define L(x)
Definition: ntvdm.h:50
_Check_return_ _CRTIMP wchar_t *__cdecl _wcsdup(_In_z_ const wchar_t *_Str)
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
char ** DuplicateEnvironment(char **original_environment, int wide)
Definition: environ.c:151
char ** __initenv
Definition: environ.c:24
wchar_t ** __winitenv
Definition: environ.c:25
wchar_t ** _wenviron
Definition: environ.c:23
char ** _environ
Definition: environ.c:22
Definition: name.c:39
Definition: getopt.h:109

Referenced by _putenv().