1 /* $Id: env.c,v 1.16 2002/09/07 15:12:40 chorns Exp $
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 #define NTOS_USER_MODE
21 /* FUNCTIONS *****************************************************************/
24 RtlCreateEnvironment(BOOLEAN Inherit
,
27 MEMORY_BASIC_INFORMATION MemInfo
;
29 NTSTATUS Status
= STATUS_SUCCESS
;
30 ULONG RegionSize
= PAGE_SIZE
;
36 if (NtCurrentPeb()->ProcessParameters
->Environment
!= NULL
)
38 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
39 NtCurrentPeb()->ProcessParameters
->Environment
,
40 MemoryBasicInformation
,
42 sizeof(MEMORY_BASIC_INFORMATION
),
44 if (!NT_SUCCESS(Status
))
51 RegionSize
= MemInfo
.RegionSize
;
52 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
56 MEM_RESERVE
| MEM_COMMIT
,
58 if (!NT_SUCCESS(Status
))
66 NtCurrentPeb ()->ProcessParameters
->Environment
,
69 *Environment
= EnvPtr
;
76 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
80 MEM_RESERVE
| MEM_COMMIT
,
82 if (NT_SUCCESS(Status
))
87 *Environment
= EnvPtr
;
96 RtlDestroyEnvironment(PWSTR Environment
)
100 NtFreeVirtualMemory(NtCurrentProcess(),
101 (PVOID
*)&Environment
,
108 RtlExpandEnvironmentStrings_U(PWSTR Environment
,
109 PUNICODE_STRING Source
,
110 PUNICODE_STRING Destination
,
115 NTSTATUS Status
= STATUS_SUCCESS
;
116 BOOLEAN flag
= FALSE
;
124 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
125 Environment
, Source
, Destination
, Length
);
127 src_len
= Source
->Length
/ sizeof(WCHAR
);
129 dst_max
= Destination
->MaximumLength
/ sizeof(WCHAR
);
130 d
= Destination
->Buffer
;
143 while (*w
!= L
'%' && tail
)
151 var
.Length
= (w
- ( s
+ 1)) * sizeof(WCHAR
);
152 var
.MaximumLength
= var
.Length
;
156 val
.MaximumLength
= dst_max
* sizeof(WCHAR
);
158 Status
= RtlQueryEnvironmentVariable_U (Environment
, &var
, &val
);
159 if (NT_SUCCESS(Status
))
161 d
+= val
.Length
/ sizeof(WCHAR
);
162 dst_max
-= val
.Length
/ sizeof(WCHAR
);
167 /* variable not found or buffer too small, just copy %var% */
173 Status
= STATUS_BUFFER_TOO_SMALL
;
182 Destination
->Length
= (d
- Destination
->Buffer
) * sizeof(WCHAR
);
184 *Length
= Destination
->Length
;
186 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
188 DPRINT("Destination %wZ\n", Destination
);
194 RtlSetCurrentEnvironment(PWSTR NewEnvironment
,
195 PWSTR
*OldEnvironment
)
199 DPRINT("NewEnvironment %x OldEnvironment %x\n",
200 NewEnvironment
, OldEnvironment
);
204 EnvPtr
= NtCurrentPeb()->ProcessParameters
->Environment
;
205 NtCurrentPeb()->ProcessParameters
->Environment
= NewEnvironment
;
207 if (OldEnvironment
!= NULL
)
208 *OldEnvironment
= EnvPtr
;
215 RtlSetEnvironmentVariable(PWSTR
*Environment
,
216 PUNICODE_STRING Name
,
217 PUNICODE_STRING Value
)
219 MEMORY_BASIC_INFORMATION mbi
;
221 int hole_len
, new_len
, env_len
= 0;
222 WCHAR
*new_env
= 0, *env_end
= 0, *wcs
, *env
, *val
= 0, *tail
= 0, *hole
= 0;
224 ULONG size
= 0, new_size
;
226 NTSTATUS Status
= STATUS_SUCCESS
;
228 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
229 Environment
, Name
, Value
);
238 env
= NtCurrentPeb()->ProcessParameters
->Environment
;
243 /* get environment length */
249 env_len
= env_end
- env
;
250 DPRINT("environment length %ld characters\n", env_len
);
252 /* find where to insert */
255 for (var
.Buffer
= wcs
++; *wcs
&& *wcs
!= L
'='; wcs
++)
259 var
.Length
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
260 var
.MaximumLength
= var
.Length
;
261 for ( val
= ++wcs
; *wcs
; wcs
++)
263 f
= RtlCompareUnicodeString(&var
, Name
, TRUE
);
266 if (f
) /* Insert before found */
268 hole
= tail
= var
.Buffer
;
270 else /* Exact match */
281 hole
= tail
= wcs
; /* Append to environment */
285 if (Value
->Length
> 0)
287 hole_len
= tail
- hole
;
288 /* calculate new environment size */
289 new_size
= Value
->Length
+ sizeof(WCHAR
);
290 /* adding new variable */
292 new_size
+= Name
->Length
+ sizeof(WCHAR
);
293 new_len
= new_size
/ sizeof(WCHAR
);
294 if (hole_len
< new_len
)
296 /* enlarge environment size */
297 /* check the size of available memory */
298 new_size
+= (env_len
- hole_len
) * sizeof(WCHAR
);
299 new_size
= ROUNDUP(new_size
, PAGE_SIZE
);
301 DPRINT("new_size %lu\n", new_size
);
305 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
311 if (!NT_SUCCESS(Status
))
313 if (Environment
== NULL
)
321 if (new_size
> mbi
.RegionSize
)
323 /* reallocate memory area */
324 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
328 MEM_RESERVE
| MEM_COMMIT
,
330 if (!NT_SUCCESS(Status
))
332 if (Environment
== NULL
)
343 (hole
- env
) * sizeof(WCHAR
));
344 hole
= new_env
+ (hole
- env
);
348 /* absolutely new environment */
349 tail
= hole
= new_env
;
357 memmove (hole
+ new_len
, tail
, (env_end
- tail
) * sizeof(WCHAR
));
361 /* we reallocated environment, let's free the old one */
363 *Environment
= new_env
;
365 NtCurrentPeb()->ProcessParameters
->Environment
= new_env
;
370 NtFreeVirtualMemory(NtCurrentProcess(),
377 /* and now copy given stuff */
380 /* copy variable name and '=' character */
384 hole
+= Name
->Length
/ sizeof(WCHAR
);
392 hole
+= Value
->Length
/ sizeof(WCHAR
);
397 /* remove the environment variable */
402 (env_end
- tail
) * sizeof(WCHAR
));
406 Status
= STATUS_VARIABLE_NOT_FOUND
;
410 if (Environment
== NULL
)
420 RtlQueryEnvironmentVariable_U(PWSTR Environment
,
421 PUNICODE_STRING Name
,
422 PUNICODE_STRING Value
)
430 BOOLEAN SysEnvUsed
= FALSE
;
432 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
433 Environment
, Name
, Value
);
435 if (Environment
== NULL
)
437 Environment
= NtCurrentPeb()->ProcessParameters
->Environment
;
441 if (Environment
== NULL
)
442 return(STATUS_VARIABLE_NOT_FOUND
);
445 if (SysEnvUsed
== TRUE
)
449 len
= Name
->Length
/ sizeof(WCHAR
);
452 for (var
= wcs
++; *wcs
&& *wcs
!= L
'='; wcs
++)
458 for (val
= ++wcs
; *wcs
; wcs
++)
462 !_wcsnicmp(var
, Name
->Buffer
, len
))
464 Value
->Length
= (wcs
- val
) * sizeof(WCHAR
);
465 if (Value
->Length
< Value
->MaximumLength
)
467 wcscpy(Value
->Buffer
, val
);
468 DPRINT("Value %S\n", val
);
469 DPRINT("Return STATUS_SUCCESS\n");
470 Status
= STATUS_SUCCESS
;
474 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
475 Status
= STATUS_BUFFER_TOO_SMALL
;
478 if (SysEnvUsed
== TRUE
)
487 if (SysEnvUsed
== TRUE
)
490 DPRINT("Return STATUS_VARIABLE_NOT_FOUND\n");
491 return(STATUS_VARIABLE_NOT_FOUND
);