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 *****************************************************************/
26 RtlCreateEnvironment(BOOLEAN Inherit,
29 MEMORY_BASIC_INFORMATION MemInfo;
31 NTSTATUS Status = STATUS_SUCCESS;
32 ULONG RegionSize = PAGE_SIZE;
38 if (NtCurrentPeb()->ProcessParameters->Environment != NULL)
40 Status = NtQueryVirtualMemory(NtCurrentProcess(),
41 NtCurrentPeb()->ProcessParameters->Environment,
42 MemoryBasicInformation,
44 sizeof(MEMORY_BASIC_INFORMATION),
46 if (!NT_SUCCESS(Status))
53 RegionSize = MemInfo.RegionSize;
54 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
58 MEM_RESERVE | MEM_COMMIT,
60 if (!NT_SUCCESS(Status))
68 NtCurrentPeb ()->ProcessParameters->Environment,
71 *Environment = EnvPtr;
78 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
82 MEM_RESERVE | MEM_COMMIT,
84 if (NT_SUCCESS(Status))
89 *Environment = EnvPtr;
98 RtlDestroyEnvironment(PWSTR Environment)
102 NtFreeVirtualMemory(NtCurrentProcess(),
103 (PVOID*)&Environment,
110 RtlExpandEnvironmentStrings_U(PWSTR Environment,
111 PUNICODE_STRING Source,
112 PUNICODE_STRING Destination,
117 NTSTATUS Status = STATUS_SUCCESS;
118 BOOLEAN flag = FALSE;
126 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
127 Environment, Source, Destination, Length);
129 src_len = Source->Length / sizeof(WCHAR);
131 dst_max = Destination->MaximumLength / sizeof(WCHAR);
132 d = Destination->Buffer;
145 while (*w != L'%' && tail)
153 var.Length = (w - ( s + 1)) * sizeof(WCHAR);
154 var.MaximumLength = var.Length;
158 val.MaximumLength = dst_max * sizeof(WCHAR);
160 Status = RtlQueryEnvironmentVariable_U (Environment, &var, &val);
161 if (NT_SUCCESS(Status))
163 d += val.Length / sizeof(WCHAR);
164 dst_max -= val.Length / sizeof(WCHAR);
169 /* variable not found or buffer too small, just copy %var% */
175 Status = STATUS_BUFFER_TOO_SMALL;
184 Destination->Length = (d - Destination->Buffer) * sizeof(WCHAR);
186 *Length = Destination->Length;
188 Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0;
190 DPRINT("Destination %wZ\n", Destination);
196 RtlSetCurrentEnvironment(PWSTR NewEnvironment,
197 PWSTR *OldEnvironment)
201 DPRINT("NewEnvironment %x OldEnvironment %x\n",
202 NewEnvironment, OldEnvironment);
206 EnvPtr = NtCurrentPeb()->ProcessParameters->Environment;
207 NtCurrentPeb()->ProcessParameters->Environment = NewEnvironment;
209 if (OldEnvironment != NULL)
210 *OldEnvironment = EnvPtr;
217 RtlSetEnvironmentVariable(PWSTR *Environment,
218 PUNICODE_STRING Name,
219 PUNICODE_STRING Value)
221 MEMORY_BASIC_INFORMATION mbi;
223 int hole_len, new_len, env_len = 0;
224 WCHAR *new_env = 0, *env_end = 0, *wcs, *env, *val = 0, *tail = 0, *hole = 0;
226 ULONG size = 0, new_size;
228 NTSTATUS Status = STATUS_SUCCESS;
230 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
231 Environment, Name, Value);
240 env = NtCurrentPeb()->ProcessParameters->Environment;
245 /* get environment length */
251 env_len = env_end - env;
252 DPRINT("environment length %ld characters\n", env_len);
254 /* find where to insert */
257 for (var.Buffer = wcs++; *wcs && *wcs != L'='; wcs++)
261 var.Length = (wcs - var.Buffer) * sizeof(WCHAR);
262 var.MaximumLength = var.Length;
263 for ( val = ++wcs; *wcs; wcs++)
265 f = RtlCompareUnicodeString(&var, Name, TRUE);
268 if (f) /* Insert before found */
270 hole = tail = var.Buffer;
272 else /* Exact match */
283 hole = tail = wcs; /* Append to environment */
287 if (Value->Length > 0)
289 hole_len = tail - hole;
290 /* calculate new environment size */
291 new_size = Value->Length + sizeof(WCHAR);
292 /* adding new variable */
294 new_size += Name->Length + sizeof(WCHAR);
295 new_len = new_size / sizeof(WCHAR);
296 if (hole_len < new_len)
298 /* enlarge environment size */
299 /* check the size of available memory */
300 new_size += (env_len - hole_len) * sizeof(WCHAR);
301 new_size = ROUNDUP(new_size, PAGE_SIZE);
303 DPRINT("new_size %lu\n", new_size);
307 Status = NtQueryVirtualMemory(NtCurrentProcess(),
313 if (!NT_SUCCESS(Status))
315 if (Environment == NULL)
323 if (new_size > mbi.RegionSize)
325 /* reallocate memory area */
326 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
330 MEM_RESERVE | MEM_COMMIT,
332 if (!NT_SUCCESS(Status))
334 if (Environment == NULL)
345 (hole - env) * sizeof(WCHAR));
346 hole = new_env + (hole - env);
350 /* absolutely new environment */
351 tail = hole = new_env;
359 memmove (hole + new_len, tail, (env_end - tail) * sizeof(WCHAR));
363 /* we reallocated environment, let's free the old one */
365 *Environment = new_env;
367 NtCurrentPeb()->ProcessParameters->Environment = new_env;
372 NtFreeVirtualMemory(NtCurrentProcess(),
379 /* and now copy given stuff */
382 /* copy variable name and '=' character */
386 hole += Name->Length / sizeof(WCHAR);
394 hole += Value->Length / sizeof(WCHAR);
399 /* remove the environment variable */
404 (env_end - tail) * sizeof(WCHAR));
408 Status = STATUS_VARIABLE_NOT_FOUND;
412 if (Environment == NULL)
422 RtlQueryEnvironmentVariable_U(PWSTR Environment,
423 PUNICODE_STRING Name,
424 PUNICODE_STRING Value)
432 BOOLEAN SysEnvUsed = FALSE;
434 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
435 Environment, Name, Value);
437 if (Environment == NULL)
439 Environment = NtCurrentPeb()->ProcessParameters->Environment;
443 if (Environment == NULL)
444 return(STATUS_VARIABLE_NOT_FOUND);
447 if (SysEnvUsed == TRUE)
451 len = Name->Length / sizeof(WCHAR);
454 for (var = wcs++; *wcs && *wcs != L'='; wcs++)
460 for (val = ++wcs; *wcs; wcs++)
464 !_wcsnicmp(var, Name->Buffer, len))
466 Value->Length = (wcs - val) * sizeof(WCHAR);
467 if (Value->Length < Value->MaximumLength)
469 wcscpy(Value->Buffer, val);
470 DPRINT("Value %S\n", val);
471 DPRINT("Return STATUS_SUCCESS\n");
472 Status = STATUS_SUCCESS;
476 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
477 Status = STATUS_BUFFER_TOO_SMALL;
480 if (SysEnvUsed == TRUE)
489 if (SysEnvUsed == TRUE)
492 DPRINT("Return STATUS_VARIABLE_NOT_FOUND\n");
493 return(STATUS_VARIABLE_NOT_FOUND);