1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
4 * PURPOSE: Environment functions
5 * PROGRAMMER: Eric Kohl
8 /* INCLUDES ******************************************************************/
15 /* FUNCTIONS *****************************************************************/
21 RtlCreateEnvironment(BOOLEAN Inherit
,
24 MEMORY_BASIC_INFORMATION MemInfo
;
26 NTSTATUS Status
= STATUS_SUCCESS
;
27 SIZE_T RegionSize
= PAGE_SIZE
;
33 if (NtCurrentPeb()->ProcessParameters
->Environment
!= NULL
)
35 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
36 NtCurrentPeb()->ProcessParameters
->Environment
,
37 MemoryBasicInformation
,
39 sizeof(MEMORY_BASIC_INFORMATION
),
41 if (!NT_SUCCESS(Status
))
48 RegionSize
= MemInfo
.RegionSize
;
49 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
53 MEM_RESERVE
| MEM_COMMIT
,
55 if (!NT_SUCCESS(Status
))
63 NtCurrentPeb ()->ProcessParameters
->Environment
,
66 *Environment
= EnvPtr
;
73 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
77 MEM_RESERVE
| MEM_COMMIT
,
79 if (NT_SUCCESS(Status
))
84 *Environment
= EnvPtr
;
96 RtlDestroyEnvironment(PWSTR Environment
)
100 NtFreeVirtualMemory(NtCurrentProcess(),
111 RtlExpandEnvironmentStrings_U(PWSTR Environment
,
112 PUNICODE_STRING Source
,
113 PUNICODE_STRING Destination
,
116 UNICODE_STRING Variable
;
117 UNICODE_STRING Value
;
118 NTSTATUS ReturnStatus
= STATUS_SUCCESS
;
128 ULONG TotalLength
= 1; /* for terminating NULL */
130 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
131 Environment
, Source
, Destination
, Length
);
133 SourceLength
= Source
->Length
/ sizeof(WCHAR
);
134 SourceBuffer
= Source
->Buffer
;
135 DestMax
= Destination
->MaximumLength
/ sizeof(WCHAR
);
136 DestBuffer
= Destination
->Buffer
;
140 if (*SourceBuffer
!= L
'%')
142 CopyBuffer
= SourceBuffer
;
144 while (SourceLength
!= 0 && *SourceBuffer
!= L
'%')
153 /* Process environment variable. */
155 VariableEnd
= SourceBuffer
+ 1;
156 Tail
= SourceLength
- 1;
157 while (*VariableEnd
!= L
'%' && Tail
!= 0)
165 Variable
.MaximumLength
=
166 Variable
.Length
= (VariableEnd
- (SourceBuffer
+ 1)) * sizeof(WCHAR
);
167 Variable
.Buffer
= SourceBuffer
+ 1;
170 Value
.MaximumLength
= DestMax
* sizeof(WCHAR
);
171 Value
.Buffer
= DestBuffer
;
173 Status
= RtlQueryEnvironmentVariable_U(Environment
, &Variable
,
175 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
177 SourceBuffer
= VariableEnd
+ 1;
178 SourceLength
= Tail
- 1;
179 TotalLength
+= Value
.Length
/ sizeof(WCHAR
);
180 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
182 DestBuffer
+= Value
.Length
/ sizeof(WCHAR
);
183 DestMax
-= Value
.Length
/ sizeof(WCHAR
);
188 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
194 /* Variable not found. */
195 CopyBuffer
= SourceBuffer
;
196 CopyLength
= SourceLength
- Tail
+ 1;
197 SourceLength
-= CopyLength
;
198 SourceBuffer
+= CopyLength
;
203 /* Unfinished variable name. */
204 CopyBuffer
= SourceBuffer
;
205 CopyLength
= SourceLength
;
210 TotalLength
+= CopyLength
;
213 if (DestMax
< CopyLength
)
215 CopyLength
= DestMax
;
216 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
218 RtlCopyMemory(DestBuffer
, CopyBuffer
, CopyLength
* sizeof(WCHAR
));
219 DestMax
-= CopyLength
;
220 DestBuffer
+= CopyLength
;
224 /* NULL-terminate the buffer. */
228 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
230 Destination
->Length
= (DestBuffer
- Destination
->Buffer
) * sizeof(WCHAR
);
232 *Length
= TotalLength
* sizeof(WCHAR
);
234 DPRINT("Destination %wZ\n", Destination
);
244 RtlSetCurrentEnvironment(PWSTR NewEnvironment
,
245 PWSTR
*OldEnvironment
)
249 DPRINT("NewEnvironment 0x%p OldEnvironment 0x%p\n",
250 NewEnvironment
, OldEnvironment
);
254 EnvPtr
= NtCurrentPeb()->ProcessParameters
->Environment
;
255 NtCurrentPeb()->ProcessParameters
->Environment
= NewEnvironment
;
257 if (OldEnvironment
!= NULL
)
258 *OldEnvironment
= EnvPtr
;
268 RtlSetEnvironmentVariable(PWSTR
*Environment
,
269 PUNICODE_STRING Name
,
270 PUNICODE_STRING Value
)
272 MEMORY_BASIC_INFORMATION mbi
;
274 int hole_len
, new_len
, env_len
= 0;
275 WCHAR
*new_env
= 0, *env_end
= 0, *wcs
, *env
, *val
= 0, *tail
= 0, *hole
= 0;
277 SIZE_T size
= 0, new_size
;
279 NTSTATUS Status
= STATUS_SUCCESS
;
281 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
282 Environment
, Name
, Value
);
284 /* Variable name must not be empty */
285 if (Name
->Length
< sizeof(WCHAR
))
286 return STATUS_INVALID_PARAMETER
;
288 /* Variable names can't contain a '=' except as a first character. */
289 for (wcs
= Name
->Buffer
+ 1;
290 wcs
< Name
->Buffer
+ (Name
->Length
/ sizeof(WCHAR
));
294 return STATUS_INVALID_PARAMETER
;
304 env
= NtCurrentPeb()->ProcessParameters
->Environment
;
309 /* get environment length */
313 env_end
+= wcslen(env_end
) + 1;
317 env_len
= env_end
- env
;
318 DPRINT("environment length %ld characters\n", env_len
);
320 /* find where to insert */
324 wcs
= wcschr(wcs
, L
'=');
327 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
331 var
.Length
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
332 var
.MaximumLength
= var
.Length
;
335 f
= RtlCompareUnicodeString(&var
, Name
, TRUE
);
338 if (f
) /* Insert before found */
340 hole
= tail
= var
.Buffer
;
342 else /* Exact match */
353 hole
= tail
= wcs
; /* Append to environment */
357 if (Value
!= NULL
&& Value
->Buffer
!= NULL
)
359 hole_len
= tail
- hole
;
360 /* calculate new environment size */
361 new_size
= Value
->Length
+ sizeof(WCHAR
);
362 /* adding new variable */
364 new_size
+= Name
->Length
+ sizeof(WCHAR
);
365 new_len
= new_size
/ sizeof(WCHAR
);
366 if (hole_len
< new_len
)
368 /* enlarge environment size */
369 /* check the size of available memory */
370 new_size
+= (env_len
- hole_len
) * sizeof(WCHAR
);
371 new_size
= ROUND_UP(new_size
, PAGE_SIZE
);
373 DPRINT("new_size %lu\n", new_size
);
377 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
379 MemoryBasicInformation
,
381 sizeof(MEMORY_BASIC_INFORMATION
),
383 if (!NT_SUCCESS(Status
))
385 if (Environment
== NULL
)
393 if (new_size
> mbi
.RegionSize
)
395 /* reallocate memory area */
396 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
400 MEM_RESERVE
| MEM_COMMIT
,
402 if (!NT_SUCCESS(Status
))
404 if (Environment
== NULL
)
415 (hole
- env
) * sizeof(WCHAR
));
416 hole
= new_env
+ (hole
- env
);
420 /* absolutely new environment */
421 tail
= hole
= new_env
;
429 memmove (hole
+ new_len
, tail
, (env_end
- tail
) * sizeof(WCHAR
));
433 /* we reallocated environment, let's free the old one */
435 *Environment
= new_env
;
437 NtCurrentPeb()->ProcessParameters
->Environment
= new_env
;
442 NtFreeVirtualMemory(NtCurrentProcess(),
449 /* and now copy given stuff */
452 /* copy variable name and '=' character */
456 hole
+= Name
->Length
/ sizeof(WCHAR
);
464 hole
+= Value
->Length
/ sizeof(WCHAR
);
469 /* remove the environment variable */
474 (env_end
- tail
) * sizeof(WCHAR
));
478 if (Environment
== NULL
)
491 RtlQueryEnvironmentVariable_U(PWSTR Environment
,
492 PUNICODE_STRING Name
,
493 PUNICODE_STRING Value
)
499 BOOLEAN SysEnvUsed
= FALSE
;
501 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
502 Environment
, Name
, Value
);
504 if (Environment
== NULL
)
506 PPEB Peb
= RtlGetCurrentPeb();
508 Environment
= Peb
->ProcessParameters
->Environment
;
513 if (Environment
== NULL
)
515 return(STATUS_VARIABLE_NOT_FOUND
);
519 if (SysEnvUsed
== TRUE
)
523 DPRINT("Starting search at :%p\n", wcs
);
527 wcs
= wcschr(wcs
, L
'=');
530 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
531 DPRINT("Search at :%S\n", wcs
);
535 var
.Length
= var
.MaximumLength
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
538 DPRINT("Search at :%S\n", wcs
);
540 if (RtlEqualUnicodeString(&var
, Name
, TRUE
))
542 Value
->Length
= (wcs
- val
) * sizeof(WCHAR
);
543 if (Value
->Length
<= Value
->MaximumLength
)
545 memcpy(Value
->Buffer
, val
,
546 min(Value
->Length
+ sizeof(WCHAR
), Value
->MaximumLength
));
547 DPRINT("Value %S\n", val
);
548 DPRINT("Return STATUS_SUCCESS\n");
549 Status
= STATUS_SUCCESS
;
553 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
554 Status
= STATUS_BUFFER_TOO_SMALL
;
557 if (SysEnvUsed
== TRUE
)
566 if (SysEnvUsed
== TRUE
)
569 DPRINT("Return STATUS_VARIABLE_NOT_FOUND: %wZ\n", Name
);
570 return(STATUS_VARIABLE_NOT_FOUND
);