3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
6 * PURPOSE: Environment functions
7 * PROGRAMMER: Eric Kohl
12 /* INCLUDES ******************************************************************/
19 PPEB STDCALL
RtlpCurrentPeb(VOID
);
20 /* 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
;
101 RtlDestroyEnvironment(PWSTR Environment
)
105 NtFreeVirtualMemory(NtCurrentProcess(),
116 RtlExpandEnvironmentStrings_U(PWSTR Environment
,
117 PUNICODE_STRING Source
,
118 PUNICODE_STRING Destination
,
121 UNICODE_STRING Variable
;
122 UNICODE_STRING Value
;
123 NTSTATUS ReturnStatus
= STATUS_SUCCESS
;
133 ULONG TotalLength
= 1; /* for terminating NULL */
135 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
136 Environment
, Source
, Destination
, Length
);
138 SourceLength
= Source
->Length
/ sizeof(WCHAR
);
139 SourceBuffer
= Source
->Buffer
;
140 DestMax
= Destination
->MaximumLength
/ sizeof(WCHAR
);
141 DestBuffer
= Destination
->Buffer
;
145 if (*SourceBuffer
!= L
'%')
147 CopyBuffer
= SourceBuffer
;
149 while (SourceLength
!= 0 && *SourceBuffer
!= L
'%')
158 /* Process environment variable. */
160 VariableEnd
= SourceBuffer
+ 1;
161 Tail
= SourceLength
- 1;
162 while (*VariableEnd
!= L
'%' && Tail
!= 0)
170 Variable
.MaximumLength
=
171 Variable
.Length
= (VariableEnd
- (SourceBuffer
+ 1)) * sizeof(WCHAR
);
172 Variable
.Buffer
= SourceBuffer
+ 1;
175 Value
.MaximumLength
= DestMax
* sizeof(WCHAR
);
176 Value
.Buffer
= DestBuffer
;
178 Status
= RtlQueryEnvironmentVariable_U(Environment
, &Variable
,
180 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
182 SourceBuffer
= VariableEnd
+ 1;
183 SourceLength
= Tail
- 1;
184 TotalLength
+= Value
.Length
/ sizeof(WCHAR
);
185 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
187 DestBuffer
+= Value
.Length
/ sizeof(WCHAR
);
188 DestMax
-= Value
.Length
/ sizeof(WCHAR
);
193 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
199 /* Variable not found. */
200 CopyBuffer
= SourceBuffer
;
201 CopyLength
= SourceLength
- Tail
+ 1;
202 SourceLength
-= CopyLength
;
203 SourceBuffer
+= CopyLength
;
208 /* Unfinished variable name. */
209 CopyBuffer
= SourceBuffer
;
210 CopyLength
= SourceLength
;
215 TotalLength
+= CopyLength
;
218 if (DestMax
< CopyLength
)
220 CopyLength
= DestMax
;
221 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
223 RtlCopyMemory(DestBuffer
, CopyBuffer
, CopyLength
* sizeof(WCHAR
));
224 DestMax
-= CopyLength
;
225 DestBuffer
+= CopyLength
;
229 /* NULL-terminate the buffer. */
233 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
235 Destination
->Length
= (DestBuffer
- Destination
->Buffer
) * sizeof(WCHAR
);
237 *Length
= TotalLength
* sizeof(WCHAR
);
239 DPRINT("Destination %wZ\n", Destination
);
249 RtlSetCurrentEnvironment(PWSTR NewEnvironment
,
250 PWSTR
*OldEnvironment
)
254 DPRINT("NewEnvironment 0x%p OldEnvironment 0x%p\n",
255 NewEnvironment
, OldEnvironment
);
259 EnvPtr
= NtCurrentPeb()->ProcessParameters
->Environment
;
260 NtCurrentPeb()->ProcessParameters
->Environment
= NewEnvironment
;
262 if (OldEnvironment
!= NULL
)
263 *OldEnvironment
= EnvPtr
;
273 RtlSetEnvironmentVariable(PWSTR
*Environment
,
274 PUNICODE_STRING Name
,
275 PUNICODE_STRING Value
)
277 MEMORY_BASIC_INFORMATION mbi
;
279 int hole_len
, new_len
, env_len
= 0;
280 WCHAR
*new_env
= 0, *env_end
= 0, *wcs
, *env
, *val
= 0, *tail
= 0, *hole
= 0;
282 ULONG size
= 0, new_size
;
284 NTSTATUS Status
= STATUS_SUCCESS
;
286 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
287 Environment
, Name
, Value
);
289 /* Variable names can't contain a '=' except as a first character. */
290 for (wcs
= Name
->Buffer
+ 1;
291 wcs
< Name
->Buffer
+ (Name
->Length
/ sizeof(WCHAR
));
295 return STATUS_INVALID_PARAMETER
;
305 env
= NtCurrentPeb()->ProcessParameters
->Environment
;
310 /* get environment length */
314 env_end
+= wcslen(env_end
) + 1;
318 env_len
= env_end
- env
;
319 DPRINT("environment length %ld characters\n", env_len
);
321 /* find where to insert */
325 wcs
= wcschr(wcs
, L
'=');
328 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
332 var
.Length
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
333 var
.MaximumLength
= var
.Length
;
336 f
= RtlCompareUnicodeString(&var
, Name
, TRUE
);
339 if (f
) /* Insert before found */
341 hole
= tail
= var
.Buffer
;
343 else /* Exact match */
354 hole
= tail
= wcs
; /* Append to environment */
358 if (Value
!= NULL
&& Value
->Length
> 0)
360 hole_len
= tail
- hole
;
361 /* calculate new environment size */
362 new_size
= Value
->Length
+ sizeof(WCHAR
);
363 /* adding new variable */
365 new_size
+= Name
->Length
+ sizeof(WCHAR
);
366 new_len
= new_size
/ sizeof(WCHAR
);
367 if (hole_len
< new_len
)
369 /* enlarge environment size */
370 /* check the size of available memory */
371 new_size
+= (env_len
- hole_len
) * sizeof(WCHAR
);
372 new_size
= ROUNDUP(new_size
, PAGE_SIZE
);
374 DPRINT("new_size %lu\n", new_size
);
378 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
380 MemoryBasicInformation
,
382 sizeof(MEMORY_BASIC_INFORMATION
),
384 if (!NT_SUCCESS(Status
))
386 if (Environment
== NULL
)
394 if (new_size
> mbi
.RegionSize
)
396 /* reallocate memory area */
397 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
401 MEM_RESERVE
| MEM_COMMIT
,
403 if (!NT_SUCCESS(Status
))
405 if (Environment
== NULL
)
416 (hole
- env
) * sizeof(WCHAR
));
417 hole
= new_env
+ (hole
- env
);
421 /* absolutely new environment */
422 tail
= hole
= new_env
;
430 memmove (hole
+ new_len
, tail
, (env_end
- tail
) * sizeof(WCHAR
));
434 /* we reallocated environment, let's free the old one */
436 *Environment
= new_env
;
438 NtCurrentPeb()->ProcessParameters
->Environment
= new_env
;
443 NtFreeVirtualMemory(NtCurrentProcess(),
450 /* and now copy given stuff */
453 /* copy variable name and '=' character */
457 hole
+= Name
->Length
/ sizeof(WCHAR
);
465 hole
+= Value
->Length
/ sizeof(WCHAR
);
470 /* remove the environment variable */
475 (env_end
- tail
) * sizeof(WCHAR
));
479 Status
= STATUS_VARIABLE_NOT_FOUND
;
483 if (Environment
== NULL
)
496 RtlQueryEnvironmentVariable_U(PWSTR Environment
,
497 PUNICODE_STRING Name
,
498 PUNICODE_STRING Value
)
504 BOOLEAN SysEnvUsed
= FALSE
;
506 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
507 Environment
, Name
, Value
);
509 if (Environment
== NULL
)
511 PPEB Peb
= RtlpCurrentPeb();
513 Environment
= Peb
->ProcessParameters
->Environment
;
518 if (Environment
== NULL
)
520 return(STATUS_VARIABLE_NOT_FOUND
);
524 if (SysEnvUsed
== TRUE
)
528 DPRINT("Starting search at :%p\n", wcs
);
532 wcs
= wcschr(wcs
, L
'=');
535 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
536 DPRINT("Search at :%S\n", wcs
);
540 var
.Length
= var
.MaximumLength
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
543 DPRINT("Search at :%S\n", wcs
);
545 if (RtlEqualUnicodeString(&var
, Name
, TRUE
))
547 Value
->Length
= (wcs
- val
) * sizeof(WCHAR
);
548 if (Value
->Length
<= Value
->MaximumLength
)
550 memcpy(Value
->Buffer
, val
,
551 min(Value
->Length
+ sizeof(WCHAR
), Value
->MaximumLength
));
552 DPRINT("Value %S\n", val
);
553 DPRINT("Return STATUS_SUCCESS\n");
554 Status
= STATUS_SUCCESS
;
558 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
559 Status
= STATUS_BUFFER_TOO_SMALL
;
562 if (SysEnvUsed
== TRUE
)
571 if (SysEnvUsed
== TRUE
)
574 DPRINT1("Return STATUS_VARIABLE_NOT_FOUND: %wZ\n", Name
);
575 return(STATUS_VARIABLE_NOT_FOUND
);