1 /* $Id: env.c,v 1.18 2002/10/01 19:27:20 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 #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
);