1 /* $Id: env.c,v 1.5 2004/12/27 20:43:42 navaraf Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
6 * PURPOSE: Environment functions
7 * PROGRAMMER: Eric Kohl
12 /* INCLUDES ******************************************************************/
14 #include <ddk/ntddk.h>
15 #include <ntdll/rtl.h>
17 #include <ntos/minmax.h>
21 #include <ntdll/ntdll.h>
23 /* FUNCTIONS *****************************************************************/
29 RtlCreateEnvironment(BOOLEAN Inherit
,
32 MEMORY_BASIC_INFORMATION MemInfo
;
34 NTSTATUS Status
= STATUS_SUCCESS
;
35 ULONG RegionSize
= PAGE_SIZE
;
41 if (NtCurrentPeb()->ProcessParameters
->Environment
!= NULL
)
43 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
44 NtCurrentPeb()->ProcessParameters
->Environment
,
45 MemoryBasicInformation
,
47 sizeof(MEMORY_BASIC_INFORMATION
),
49 if (!NT_SUCCESS(Status
))
56 RegionSize
= MemInfo
.RegionSize
;
57 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
61 MEM_RESERVE
| MEM_COMMIT
,
63 if (!NT_SUCCESS(Status
))
71 NtCurrentPeb ()->ProcessParameters
->Environment
,
74 *Environment
= EnvPtr
;
81 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
85 MEM_RESERVE
| MEM_COMMIT
,
87 if (NT_SUCCESS(Status
))
92 *Environment
= EnvPtr
;
104 RtlDestroyEnvironment(PWSTR Environment
)
108 NtFreeVirtualMemory(NtCurrentProcess(),
119 RtlExpandEnvironmentStrings_U(PWSTR Environment
,
120 PUNICODE_STRING Source
,
121 PUNICODE_STRING Destination
,
124 UNICODE_STRING Variable
;
125 UNICODE_STRING Value
;
126 NTSTATUS ReturnStatus
= STATUS_SUCCESS
;
136 ULONG TotalLength
= 1; /* for terminating NULL */
138 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
139 Environment
, Source
, Destination
, Length
);
141 SourceLength
= Source
->Length
/ sizeof(WCHAR
);
142 SourceBuffer
= Source
->Buffer
;
143 DestMax
= Destination
->MaximumLength
/ sizeof(WCHAR
);
144 DestBuffer
= Destination
->Buffer
;
148 if (*SourceBuffer
!= L
'%')
150 CopyBuffer
= SourceBuffer
;
152 while (SourceLength
!= 0 && *SourceBuffer
!= L
'%')
161 /* Process environment variable. */
163 VariableEnd
= SourceBuffer
+ 1;
164 Tail
= SourceLength
- 1;
165 while (*VariableEnd
!= L
'%' && Tail
!= 0)
173 Variable
.MaximumLength
=
174 Variable
.Length
= (VariableEnd
- (SourceBuffer
+ 1)) * sizeof(WCHAR
);
175 Variable
.Buffer
= SourceBuffer
+ 1;
178 Value
.MaximumLength
= DestMax
* sizeof(WCHAR
);
179 Value
.Buffer
= DestBuffer
;
181 Status
= RtlQueryEnvironmentVariable_U(Environment
, &Variable
,
183 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
185 SourceBuffer
= VariableEnd
+ 1;
186 SourceLength
= Tail
- 1;
187 TotalLength
+= Value
.Length
/ sizeof(WCHAR
);
188 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
190 DestBuffer
+= Value
.Length
/ sizeof(WCHAR
);
191 DestMax
-= Value
.Length
/ sizeof(WCHAR
);
196 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
202 /* Variable not found. */
203 CopyBuffer
= SourceBuffer
;
204 CopyLength
= SourceLength
- Tail
+ 1;
205 SourceLength
-= CopyLength
;
206 SourceBuffer
+= CopyLength
;
211 /* Unfinished variable name. */
212 CopyBuffer
= SourceBuffer
;
213 CopyLength
= SourceLength
;
218 TotalLength
+= CopyLength
;
221 if (DestMax
< CopyLength
)
223 CopyLength
= DestMax
;
224 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
226 RtlCopyMemory(DestBuffer
, CopyBuffer
, CopyLength
* sizeof(WCHAR
));
227 DestMax
-= CopyLength
;
228 DestBuffer
+= CopyLength
;
232 /* NULL-terminate the buffer. */
236 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
238 Destination
->Length
= (DestBuffer
- Destination
->Buffer
) * sizeof(WCHAR
);
240 *Length
= TotalLength
* sizeof(WCHAR
);
242 DPRINT("Destination %wZ\n", Destination
);
252 RtlSetCurrentEnvironment(PWSTR NewEnvironment
,
253 PWSTR
*OldEnvironment
)
257 DPRINT("NewEnvironment %x OldEnvironment %x\n",
258 NewEnvironment
, OldEnvironment
);
262 EnvPtr
= NtCurrentPeb()->ProcessParameters
->Environment
;
263 NtCurrentPeb()->ProcessParameters
->Environment
= NewEnvironment
;
265 if (OldEnvironment
!= NULL
)
266 *OldEnvironment
= EnvPtr
;
276 RtlSetEnvironmentVariable(PWSTR
*Environment
,
277 PUNICODE_STRING Name
,
278 PUNICODE_STRING Value
)
280 MEMORY_BASIC_INFORMATION mbi
;
282 int hole_len
, new_len
, env_len
= 0;
283 WCHAR
*new_env
= 0, *env_end
= 0, *wcs
, *env
, *val
= 0, *tail
= 0, *hole
= 0;
285 ULONG size
= 0, new_size
;
287 NTSTATUS Status
= STATUS_SUCCESS
;
289 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
290 Environment
, Name
, Value
);
292 /* Variable names can't contain a '=' except as a first character. */
293 for (wcs
= Name
->Buffer
+ 1;
294 wcs
< Name
->Buffer
+ (Name
->Length
/ sizeof(WCHAR
));
298 return STATUS_INVALID_PARAMETER
;
308 env
= NtCurrentPeb()->ProcessParameters
->Environment
;
313 /* get environment length */
317 env_end
+= wcslen(env_end
) + 1;
321 env_len
= env_end
- env
;
322 DPRINT("environment length %ld characters\n", env_len
);
324 /* find where to insert */
328 wcs
= wcschr(wcs
, L
'=');
331 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
335 var
.Length
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
336 var
.MaximumLength
= var
.Length
;
339 f
= RtlCompareUnicodeString(&var
, Name
, TRUE
);
342 if (f
) /* Insert before found */
344 hole
= tail
= var
.Buffer
;
346 else /* Exact match */
357 hole
= tail
= wcs
; /* Append to environment */
361 if (Value
!= NULL
&& Value
->Length
> 0)
363 hole_len
= tail
- hole
;
364 /* calculate new environment size */
365 new_size
= Value
->Length
+ sizeof(WCHAR
);
366 /* adding new variable */
368 new_size
+= Name
->Length
+ sizeof(WCHAR
);
369 new_len
= new_size
/ sizeof(WCHAR
);
370 if (hole_len
< new_len
)
372 /* enlarge environment size */
373 /* check the size of available memory */
374 new_size
+= (env_len
- hole_len
) * sizeof(WCHAR
);
375 new_size
= ROUNDUP(new_size
, PAGE_SIZE
);
377 DPRINT("new_size %lu\n", new_size
);
381 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
383 MemoryBasicInformation
,
385 sizeof(MEMORY_BASIC_INFORMATION
),
387 if (!NT_SUCCESS(Status
))
389 if (Environment
== NULL
)
397 if (new_size
> mbi
.RegionSize
)
399 /* reallocate memory area */
400 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
404 MEM_RESERVE
| MEM_COMMIT
,
406 if (!NT_SUCCESS(Status
))
408 if (Environment
== NULL
)
419 (hole
- env
) * sizeof(WCHAR
));
420 hole
= new_env
+ (hole
- env
);
424 /* absolutely new environment */
425 tail
= hole
= new_env
;
433 memmove (hole
+ new_len
, tail
, (env_end
- tail
) * sizeof(WCHAR
));
437 /* we reallocated environment, let's free the old one */
439 *Environment
= new_env
;
441 NtCurrentPeb()->ProcessParameters
->Environment
= new_env
;
446 NtFreeVirtualMemory(NtCurrentProcess(),
453 /* and now copy given stuff */
456 /* copy variable name and '=' character */
460 hole
+= Name
->Length
/ sizeof(WCHAR
);
468 hole
+= Value
->Length
/ sizeof(WCHAR
);
473 /* remove the environment variable */
478 (env_end
- tail
) * sizeof(WCHAR
));
482 Status
= STATUS_VARIABLE_NOT_FOUND
;
486 if (Environment
== NULL
)
499 RtlQueryEnvironmentVariable_U(PWSTR Environment
,
500 PUNICODE_STRING Name
,
501 PUNICODE_STRING Value
)
507 BOOLEAN SysEnvUsed
= FALSE
;
509 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
510 Environment
, Name
, Value
);
512 if (Environment
== NULL
)
514 Environment
= NtCurrentPeb()->ProcessParameters
->Environment
;
518 if (Environment
== NULL
)
519 return(STATUS_VARIABLE_NOT_FOUND
);
522 if (SysEnvUsed
== TRUE
)
529 wcs
= wcschr(wcs
, L
'=');
532 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
536 var
.Length
= var
.MaximumLength
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
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\n");
570 return(STATUS_VARIABLE_NOT_FOUND
);