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 PPEB NTAPI
RtlpCurrentPeb(VOID
);
16 /* FUNCTIONS *****************************************************************/
22 RtlCreateEnvironment(BOOLEAN Inherit
,
25 MEMORY_BASIC_INFORMATION MemInfo
;
27 NTSTATUS Status
= STATUS_SUCCESS
;
28 ULONG RegionSize
= PAGE_SIZE
;
34 if (NtCurrentPeb()->ProcessParameters
->Environment
!= NULL
)
36 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
37 NtCurrentPeb()->ProcessParameters
->Environment
,
38 MemoryBasicInformation
,
40 sizeof(MEMORY_BASIC_INFORMATION
),
42 if (!NT_SUCCESS(Status
))
49 RegionSize
= MemInfo
.RegionSize
;
50 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
54 MEM_RESERVE
| MEM_COMMIT
,
56 if (!NT_SUCCESS(Status
))
64 NtCurrentPeb ()->ProcessParameters
->Environment
,
67 *Environment
= EnvPtr
;
74 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
78 MEM_RESERVE
| MEM_COMMIT
,
80 if (NT_SUCCESS(Status
))
85 *Environment
= EnvPtr
;
97 RtlDestroyEnvironment(PWSTR Environment
)
101 NtFreeVirtualMemory(NtCurrentProcess(),
112 RtlExpandEnvironmentStrings_U(PWSTR Environment
,
113 PUNICODE_STRING Source
,
114 PUNICODE_STRING Destination
,
117 UNICODE_STRING Variable
;
118 UNICODE_STRING Value
;
119 NTSTATUS ReturnStatus
= STATUS_SUCCESS
;
129 ULONG TotalLength
= 1; /* for terminating NULL */
131 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
132 Environment
, Source
, Destination
, Length
);
134 SourceLength
= Source
->Length
/ sizeof(WCHAR
);
135 SourceBuffer
= Source
->Buffer
;
136 DestMax
= Destination
->MaximumLength
/ sizeof(WCHAR
);
137 DestBuffer
= Destination
->Buffer
;
141 if (*SourceBuffer
!= L
'%')
143 CopyBuffer
= SourceBuffer
;
145 while (SourceLength
!= 0 && *SourceBuffer
!= L
'%')
154 /* Process environment variable. */
156 VariableEnd
= SourceBuffer
+ 1;
157 Tail
= SourceLength
- 1;
158 while (*VariableEnd
!= L
'%' && Tail
!= 0)
166 Variable
.MaximumLength
=
167 Variable
.Length
= (VariableEnd
- (SourceBuffer
+ 1)) * sizeof(WCHAR
);
168 Variable
.Buffer
= SourceBuffer
+ 1;
171 Value
.MaximumLength
= DestMax
* sizeof(WCHAR
);
172 Value
.Buffer
= DestBuffer
;
174 Status
= RtlQueryEnvironmentVariable_U(Environment
, &Variable
,
176 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
178 SourceBuffer
= VariableEnd
+ 1;
179 SourceLength
= Tail
- 1;
180 TotalLength
+= Value
.Length
/ sizeof(WCHAR
);
181 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
183 DestBuffer
+= Value
.Length
/ sizeof(WCHAR
);
184 DestMax
-= Value
.Length
/ sizeof(WCHAR
);
189 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
195 /* Variable not found. */
196 CopyBuffer
= SourceBuffer
;
197 CopyLength
= SourceLength
- Tail
+ 1;
198 SourceLength
-= CopyLength
;
199 SourceBuffer
+= CopyLength
;
204 /* Unfinished variable name. */
205 CopyBuffer
= SourceBuffer
;
206 CopyLength
= SourceLength
;
211 TotalLength
+= CopyLength
;
214 if (DestMax
< CopyLength
)
216 CopyLength
= DestMax
;
217 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
219 RtlCopyMemory(DestBuffer
, CopyBuffer
, CopyLength
* sizeof(WCHAR
));
220 DestMax
-= CopyLength
;
221 DestBuffer
+= CopyLength
;
225 /* NULL-terminate the buffer. */
229 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
231 Destination
->Length
= (DestBuffer
- Destination
->Buffer
) * sizeof(WCHAR
);
233 *Length
= TotalLength
* sizeof(WCHAR
);
235 DPRINT("Destination %wZ\n", Destination
);
245 RtlSetCurrentEnvironment(PWSTR NewEnvironment
,
246 PWSTR
*OldEnvironment
)
250 DPRINT("NewEnvironment 0x%p OldEnvironment 0x%p\n",
251 NewEnvironment
, OldEnvironment
);
255 EnvPtr
= NtCurrentPeb()->ProcessParameters
->Environment
;
256 NtCurrentPeb()->ProcessParameters
->Environment
= NewEnvironment
;
258 if (OldEnvironment
!= NULL
)
259 *OldEnvironment
= EnvPtr
;
269 RtlSetEnvironmentVariable(PWSTR
*Environment
,
270 PUNICODE_STRING Name
,
271 PUNICODE_STRING Value
)
273 MEMORY_BASIC_INFORMATION mbi
;
275 int hole_len
, new_len
, env_len
= 0;
276 WCHAR
*new_env
= 0, *env_end
= 0, *wcs
, *env
, *val
= 0, *tail
= 0, *hole
= 0;
278 ULONG size
= 0, new_size
;
280 NTSTATUS Status
= STATUS_SUCCESS
;
282 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
283 Environment
, Name
, Value
);
285 /* Variable names can't contain a '=' except as a first character. */
286 for (wcs
= Name
->Buffer
+ 1;
287 wcs
< Name
->Buffer
+ (Name
->Length
/ sizeof(WCHAR
));
291 return STATUS_INVALID_PARAMETER
;
301 env
= NtCurrentPeb()->ProcessParameters
->Environment
;
306 /* get environment length */
310 env_end
+= wcslen(env_end
) + 1;
314 env_len
= env_end
- env
;
315 DPRINT("environment length %ld characters\n", env_len
);
317 /* find where to insert */
321 wcs
= wcschr(wcs
, L
'=');
324 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
328 var
.Length
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
329 var
.MaximumLength
= var
.Length
;
332 f
= RtlCompareUnicodeString(&var
, Name
, TRUE
);
335 if (f
) /* Insert before found */
337 hole
= tail
= var
.Buffer
;
339 else /* Exact match */
350 hole
= tail
= wcs
; /* Append to environment */
354 if (Value
!= NULL
&& Value
->Length
> 0)
356 hole_len
= tail
- hole
;
357 /* calculate new environment size */
358 new_size
= Value
->Length
+ sizeof(WCHAR
);
359 /* adding new variable */
361 new_size
+= Name
->Length
+ sizeof(WCHAR
);
362 new_len
= new_size
/ sizeof(WCHAR
);
363 if (hole_len
< new_len
)
365 /* enlarge environment size */
366 /* check the size of available memory */
367 new_size
+= (env_len
- hole_len
) * sizeof(WCHAR
);
368 new_size
= ROUNDUP(new_size
, PAGE_SIZE
);
370 DPRINT("new_size %lu\n", new_size
);
374 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
376 MemoryBasicInformation
,
378 sizeof(MEMORY_BASIC_INFORMATION
),
380 if (!NT_SUCCESS(Status
))
382 if (Environment
== NULL
)
390 if (new_size
> mbi
.RegionSize
)
392 /* reallocate memory area */
393 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
397 MEM_RESERVE
| MEM_COMMIT
,
399 if (!NT_SUCCESS(Status
))
401 if (Environment
== NULL
)
412 (hole
- env
) * sizeof(WCHAR
));
413 hole
= new_env
+ (hole
- env
);
417 /* absolutely new environment */
418 tail
= hole
= new_env
;
426 memmove (hole
+ new_len
, tail
, (env_end
- tail
) * sizeof(WCHAR
));
430 /* we reallocated environment, let's free the old one */
432 *Environment
= new_env
;
434 NtCurrentPeb()->ProcessParameters
->Environment
= new_env
;
439 NtFreeVirtualMemory(NtCurrentProcess(),
446 /* and now copy given stuff */
449 /* copy variable name and '=' character */
453 hole
+= Name
->Length
/ sizeof(WCHAR
);
461 hole
+= Value
->Length
/ sizeof(WCHAR
);
466 /* remove the environment variable */
471 (env_end
- tail
) * sizeof(WCHAR
));
475 Status
= STATUS_VARIABLE_NOT_FOUND
;
479 if (Environment
== NULL
)
492 RtlQueryEnvironmentVariable_U(PWSTR Environment
,
493 PUNICODE_STRING Name
,
494 PUNICODE_STRING Value
)
500 BOOLEAN SysEnvUsed
= FALSE
;
502 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
503 Environment
, Name
, Value
);
505 if (Environment
== NULL
)
507 PPEB Peb
= RtlpCurrentPeb();
509 Environment
= Peb
->ProcessParameters
->Environment
;
514 if (Environment
== NULL
)
516 return(STATUS_VARIABLE_NOT_FOUND
);
520 if (SysEnvUsed
== TRUE
)
524 DPRINT("Starting search at :%p\n", wcs
);
528 wcs
= wcschr(wcs
, L
'=');
531 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
532 DPRINT("Search at :%S\n", wcs
);
536 var
.Length
= var
.MaximumLength
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
539 DPRINT("Search at :%S\n", wcs
);
541 if (RtlEqualUnicodeString(&var
, Name
, TRUE
))
543 Value
->Length
= (wcs
- val
) * sizeof(WCHAR
);
544 if (Value
->Length
<= Value
->MaximumLength
)
546 memcpy(Value
->Buffer
, val
,
547 min(Value
->Length
+ sizeof(WCHAR
), Value
->MaximumLength
));
548 DPRINT("Value %S\n", val
);
549 DPRINT("Return STATUS_SUCCESS\n");
550 Status
= STATUS_SUCCESS
;
554 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
555 Status
= STATUS_BUFFER_TOO_SMALL
;
558 if (SysEnvUsed
== TRUE
)
567 if (SysEnvUsed
== TRUE
)
570 DPRINT("Return STATUS_VARIABLE_NOT_FOUND: %wZ\n", Name
);
571 return(STATUS_VARIABLE_NOT_FOUND
);