3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/ntdll/rtl/env.c
6 * PURPOSE: Environment functions
7 * PROGRAMMER: Eric Kohl
12 /* INCLUDES ******************************************************************/
14 #include <ddk/ntddk.h>
15 #include <ntdll/rtl.h>
20 #include <ntdll/ntdll.h>
23 /* FUNCTIONS *****************************************************************/
29 RtlCreateEnvironment(BOOLEAN Inherit,
33 NTSTATUS Status = STATUS_SUCCESS;
34 ULONG RegionSize = PAGE_SIZE;
40 if (NtCurrentPeb()->ProcessParameters->Environment != NULL)
42 Status = NtQueryVirtualMemory(NtCurrentProcess(),
43 NtCurrentPeb()->ProcessParameters->Environment,
44 MemoryBasicInformation,
46 sizeof(MEMORY_BASIC_INFORMATION),
48 if (!NT_SUCCESS(Status))
55 RegionSize = MemInfo.RegionSize;
56 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
60 MEM_RESERVE | MEM_COMMIT,
62 if (!NT_SUCCESS(Status))
70 NtCurrentPeb ()->ProcessParameters->Environment,
73 *Environment = EnvPtr;
80 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
84 MEM_RESERVE | MEM_COMMIT,
86 if (NT_SUCCESS(Status))
91 *Environment = EnvPtr;
103 RtlDestroyEnvironment(PWSTR Environment)
107 NtFreeVirtualMemory(NtCurrentProcess(),
108 (PVOID*)&Environment,
118 RtlExpandEnvironmentStrings_U(PWSTR Environment,
119 PUNICODE_STRING Source,
120 PUNICODE_STRING Destination,
125 NTSTATUS Status = STATUS_SUCCESS;
126 BOOLEAN flag = FALSE;
134 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
135 Environment, Source, Destination, Length);
137 src_len = Source->Length / sizeof(WCHAR);
139 dst_max = Destination->MaximumLength / sizeof(WCHAR);
140 d = Destination->Buffer;
153 while (*w != L'%' && tail)
161 var.Length = (w - ( s + 1)) * sizeof(WCHAR);
162 var.MaximumLength = var.Length;
166 val.MaximumLength = dst_max * sizeof(WCHAR);
168 Status = RtlQueryEnvironmentVariable_U (Environment, &var, &val);
169 if (NT_SUCCESS(Status))
171 d += val.Length / sizeof(WCHAR);
172 dst_max -= val.Length / sizeof(WCHAR);
177 /* variable not found or buffer too small, just copy %var% */
183 Status = STATUS_BUFFER_TOO_SMALL;
192 Destination->Length = (d - Destination->Buffer) * sizeof(WCHAR);
194 *Length = Destination->Length;
196 Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0;
198 DPRINT("Destination %wZ\n", Destination);
207 RtlSetCurrentEnvironment(PWSTR NewEnvironment,
208 PWSTR *OldEnvironment)
212 DPRINT("NewEnvironment %x OldEnvironment %x\n",
213 NewEnvironment, OldEnvironment);
217 EnvPtr = NtCurrentPeb()->ProcessParameters->Environment;
218 NtCurrentPeb()->ProcessParameters->Environment = NewEnvironment;
220 if (OldEnvironment != NULL)
221 *OldEnvironment = EnvPtr;
231 RtlSetEnvironmentVariable(PWSTR *Environment,
232 PUNICODE_STRING Name,
233 PUNICODE_STRING Value)
235 MEMORY_BASIC_INFORMATION mbi;
237 int hole_len, new_len, env_len = 0;
238 WCHAR *new_env = 0, *env_end = 0, *wcs, *env, *val = 0, *tail = 0, *hole = 0;
240 ULONG size = 0, new_size;
242 NTSTATUS Status = STATUS_SUCCESS;
244 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
245 Environment, Name, Value);
254 env = NtCurrentPeb()->ProcessParameters->Environment;
259 /* get environment length */
263 env_end += wcslen(env_end) + 1;
267 env_len = env_end - env;
268 DPRINT("environment length %ld characters\n", env_len);
270 /* find where to insert */
274 wcs = wcschr(wcs, L'=');
277 wcs = var.Buffer + wcslen(var.Buffer);
281 var.Length = (wcs - var.Buffer) * sizeof(WCHAR);
282 var.MaximumLength = var.Length;
285 f = RtlCompareUnicodeString(&var, Name, TRUE);
288 if (f) /* Insert before found */
290 hole = tail = var.Buffer;
292 else /* Exact match */
303 hole = tail = wcs; /* Append to environment */
307 if (Value->Length > 0)
309 hole_len = tail - hole;
310 /* calculate new environment size */
311 new_size = Value->Length + sizeof(WCHAR);
312 /* adding new variable */
314 new_size += Name->Length + sizeof(WCHAR);
315 new_len = new_size / sizeof(WCHAR);
316 if (hole_len < new_len)
318 /* enlarge environment size */
319 /* check the size of available memory */
320 new_size += (env_len - hole_len) * sizeof(WCHAR);
321 new_size = ROUNDUP(new_size, PAGE_SIZE);
323 DPRINT("new_size %lu\n", new_size);
327 Status = NtQueryVirtualMemory(NtCurrentProcess(),
333 if (!NT_SUCCESS(Status))
335 if (Environment == NULL)
343 if (new_size > mbi.RegionSize)
345 /* reallocate memory area */
346 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
350 MEM_RESERVE | MEM_COMMIT,
352 if (!NT_SUCCESS(Status))
354 if (Environment == NULL)
365 (hole - env) * sizeof(WCHAR));
366 hole = new_env + (hole - env);
370 /* absolutely new environment */
371 tail = hole = new_env;
379 memmove (hole + new_len, tail, (env_end - tail) * sizeof(WCHAR));
383 /* we reallocated environment, let's free the old one */
385 *Environment = new_env;
387 NtCurrentPeb()->ProcessParameters->Environment = new_env;
392 NtFreeVirtualMemory(NtCurrentProcess(),
399 /* and now copy given stuff */
402 /* copy variable name and '=' character */
406 hole += Name->Length / sizeof(WCHAR);
414 hole += Value->Length / sizeof(WCHAR);
419 /* remove the environment variable */
424 (env_end - tail) * sizeof(WCHAR));
428 Status = STATUS_VARIABLE_NOT_FOUND;
432 if (Environment == NULL)
445 RtlQueryEnvironmentVariable_U(PWSTR Environment,
446 PUNICODE_STRING Name,
447 PUNICODE_STRING Value)
454 BOOLEAN SysEnvUsed = FALSE;
456 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
457 Environment, Name, Value);
459 if (Environment == NULL)
461 Environment = NtCurrentPeb()->ProcessParameters->Environment;
465 if (Environment == NULL)
466 return(STATUS_VARIABLE_NOT_FOUND);
469 if (SysEnvUsed == TRUE)
473 len = Name->Length / sizeof(WCHAR);
477 wcs = wcschr(wcs, L'=');
480 wcs = var.Buffer + wcslen(var.Buffer);
484 var.Length = var.MaximumLength = (wcs - var.Buffer) * sizeof(WCHAR);
488 if (RtlEqualUnicodeString(&var, Name, TRUE))
490 Value->Length = (wcs - val) * sizeof(WCHAR);
491 if (Value->Length < Value->MaximumLength)
493 memcpy(Value->Buffer, val, Value->Length + sizeof(WCHAR));
494 DPRINT("Value %S\n", val);
495 DPRINT("Return STATUS_SUCCESS\n");
496 Status = STATUS_SUCCESS;
500 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
501 Status = STATUS_BUFFER_TOO_SMALL;
504 if (SysEnvUsed == TRUE)
513 if (SysEnvUsed == TRUE)
516 DPRINT("Return STATUS_VARIABLE_NOT_FOUND\n");
517 return(STATUS_VARIABLE_NOT_FOUND);