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 *****************************************************************/
25 /* FIXME: Added here temporarly until I fix this properly tomorrow */
30 RtlAcquirePebLock(VOID
)
32 PPEB Peb
= NtCurrentPeb ();
33 Peb
->FastPebLockRoutine (Peb
->FastPebLock
);
36 /* FIXME: Added here temporarly until I fix this properly tomorrow */
41 RtlReleasePebLock(VOID
)
43 PPEB Peb
= NtCurrentPeb ();
44 Peb
->FastPebUnlockRoutine (Peb
->FastPebLock
);
51 RtlCreateEnvironment(BOOLEAN Inherit
,
54 MEMORY_BASIC_INFORMATION MemInfo
;
56 NTSTATUS Status
= STATUS_SUCCESS
;
57 ULONG RegionSize
= PAGE_SIZE
;
63 if (NtCurrentPeb()->ProcessParameters
->Environment
!= NULL
)
65 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
66 NtCurrentPeb()->ProcessParameters
->Environment
,
67 MemoryBasicInformation
,
69 sizeof(MEMORY_BASIC_INFORMATION
),
71 if (!NT_SUCCESS(Status
))
78 RegionSize
= MemInfo
.RegionSize
;
79 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
83 MEM_RESERVE
| MEM_COMMIT
,
85 if (!NT_SUCCESS(Status
))
93 NtCurrentPeb ()->ProcessParameters
->Environment
,
96 *Environment
= EnvPtr
;
103 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
107 MEM_RESERVE
| MEM_COMMIT
,
109 if (NT_SUCCESS(Status
))
114 *Environment
= EnvPtr
;
126 RtlDestroyEnvironment(PWSTR Environment
)
130 NtFreeVirtualMemory(NtCurrentProcess(),
141 RtlExpandEnvironmentStrings_U(PWSTR Environment
,
142 PUNICODE_STRING Source
,
143 PUNICODE_STRING Destination
,
146 UNICODE_STRING Variable
;
147 UNICODE_STRING Value
;
148 NTSTATUS ReturnStatus
= STATUS_SUCCESS
;
158 ULONG TotalLength
= 1; /* for terminating NULL */
160 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
161 Environment
, Source
, Destination
, Length
);
163 SourceLength
= Source
->Length
/ sizeof(WCHAR
);
164 SourceBuffer
= Source
->Buffer
;
165 DestMax
= Destination
->MaximumLength
/ sizeof(WCHAR
);
166 DestBuffer
= Destination
->Buffer
;
170 if (*SourceBuffer
!= L
'%')
172 CopyBuffer
= SourceBuffer
;
174 while (SourceLength
!= 0 && *SourceBuffer
!= L
'%')
183 /* Process environment variable. */
185 VariableEnd
= SourceBuffer
+ 1;
186 Tail
= SourceLength
- 1;
187 while (*VariableEnd
!= L
'%' && Tail
!= 0)
195 Variable
.MaximumLength
=
196 Variable
.Length
= (VariableEnd
- (SourceBuffer
+ 1)) * sizeof(WCHAR
);
197 Variable
.Buffer
= SourceBuffer
+ 1;
200 Value
.MaximumLength
= DestMax
* sizeof(WCHAR
);
201 Value
.Buffer
= DestBuffer
;
203 Status
= RtlQueryEnvironmentVariable_U(Environment
, &Variable
,
205 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
207 SourceBuffer
= VariableEnd
+ 1;
208 SourceLength
= Tail
- 1;
209 TotalLength
+= Value
.Length
/ sizeof(WCHAR
);
210 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
212 DestBuffer
+= Value
.Length
/ sizeof(WCHAR
);
213 DestMax
-= Value
.Length
/ sizeof(WCHAR
);
218 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
224 /* Variable not found. */
225 CopyBuffer
= SourceBuffer
;
226 CopyLength
= SourceLength
- Tail
+ 1;
227 SourceLength
-= CopyLength
;
228 SourceBuffer
+= CopyLength
;
233 /* Unfinished variable name. */
234 CopyBuffer
= SourceBuffer
;
235 CopyLength
= SourceLength
;
240 TotalLength
+= CopyLength
;
243 if (DestMax
< CopyLength
)
245 CopyLength
= DestMax
;
246 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
248 RtlCopyMemory(DestBuffer
, CopyBuffer
, CopyLength
* sizeof(WCHAR
));
249 DestMax
-= CopyLength
;
250 DestBuffer
+= CopyLength
;
254 /* NULL-terminate the buffer. */
258 ReturnStatus
= STATUS_BUFFER_TOO_SMALL
;
260 Destination
->Length
= (DestBuffer
- Destination
->Buffer
) * sizeof(WCHAR
);
262 *Length
= TotalLength
* sizeof(WCHAR
);
264 DPRINT("Destination %wZ\n", Destination
);
274 RtlSetCurrentEnvironment(PWSTR NewEnvironment
,
275 PWSTR
*OldEnvironment
)
279 DPRINT("NewEnvironment %x OldEnvironment %x\n",
280 NewEnvironment
, OldEnvironment
);
284 EnvPtr
= NtCurrentPeb()->ProcessParameters
->Environment
;
285 NtCurrentPeb()->ProcessParameters
->Environment
= NewEnvironment
;
287 if (OldEnvironment
!= NULL
)
288 *OldEnvironment
= EnvPtr
;
298 RtlSetEnvironmentVariable(PWSTR
*Environment
,
299 PUNICODE_STRING Name
,
300 PUNICODE_STRING Value
)
302 MEMORY_BASIC_INFORMATION mbi
;
304 int hole_len
, new_len
, env_len
= 0;
305 WCHAR
*new_env
= 0, *env_end
= 0, *wcs
, *env
, *val
= 0, *tail
= 0, *hole
= 0;
307 ULONG size
= 0, new_size
;
309 NTSTATUS Status
= STATUS_SUCCESS
;
311 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
312 Environment
, Name
, Value
);
314 /* Variable names can't contain a '=' except as a first character. */
315 for (wcs
= Name
->Buffer
+ 1;
316 wcs
< Name
->Buffer
+ (Name
->Length
/ sizeof(WCHAR
));
320 return STATUS_INVALID_PARAMETER
;
330 env
= NtCurrentPeb()->ProcessParameters
->Environment
;
335 /* get environment length */
339 env_end
+= wcslen(env_end
) + 1;
343 env_len
= env_end
- env
;
344 DPRINT("environment length %ld characters\n", env_len
);
346 /* find where to insert */
350 wcs
= wcschr(wcs
, L
'=');
353 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
357 var
.Length
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
358 var
.MaximumLength
= var
.Length
;
361 f
= RtlCompareUnicodeString(&var
, Name
, TRUE
);
364 if (f
) /* Insert before found */
366 hole
= tail
= var
.Buffer
;
368 else /* Exact match */
379 hole
= tail
= wcs
; /* Append to environment */
383 if (Value
!= NULL
&& Value
->Length
> 0)
385 hole_len
= tail
- hole
;
386 /* calculate new environment size */
387 new_size
= Value
->Length
+ sizeof(WCHAR
);
388 /* adding new variable */
390 new_size
+= Name
->Length
+ sizeof(WCHAR
);
391 new_len
= new_size
/ sizeof(WCHAR
);
392 if (hole_len
< new_len
)
394 /* enlarge environment size */
395 /* check the size of available memory */
396 new_size
+= (env_len
- hole_len
) * sizeof(WCHAR
);
397 new_size
= ROUNDUP(new_size
, PAGE_SIZE
);
399 DPRINT("new_size %lu\n", new_size
);
403 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
405 MemoryBasicInformation
,
407 sizeof(MEMORY_BASIC_INFORMATION
),
409 if (!NT_SUCCESS(Status
))
411 if (Environment
== NULL
)
419 if (new_size
> mbi
.RegionSize
)
421 /* reallocate memory area */
422 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
426 MEM_RESERVE
| MEM_COMMIT
,
428 if (!NT_SUCCESS(Status
))
430 if (Environment
== NULL
)
441 (hole
- env
) * sizeof(WCHAR
));
442 hole
= new_env
+ (hole
- env
);
446 /* absolutely new environment */
447 tail
= hole
= new_env
;
455 memmove (hole
+ new_len
, tail
, (env_end
- tail
) * sizeof(WCHAR
));
459 /* we reallocated environment, let's free the old one */
461 *Environment
= new_env
;
463 NtCurrentPeb()->ProcessParameters
->Environment
= new_env
;
468 NtFreeVirtualMemory(NtCurrentProcess(),
475 /* and now copy given stuff */
478 /* copy variable name and '=' character */
482 hole
+= Name
->Length
/ sizeof(WCHAR
);
490 hole
+= Value
->Length
/ sizeof(WCHAR
);
495 /* remove the environment variable */
500 (env_end
- tail
) * sizeof(WCHAR
));
504 Status
= STATUS_VARIABLE_NOT_FOUND
;
508 if (Environment
== NULL
)
521 RtlQueryEnvironmentVariable_U(PWSTR Environment
,
522 PUNICODE_STRING Name
,
523 PUNICODE_STRING Value
)
529 BOOLEAN SysEnvUsed
= FALSE
;
531 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
532 Environment
, Name
, Value
);
534 if (Environment
== NULL
)
536 if (NtCurrentPeb() == NULL
)
538 return(STATUS_VARIABLE_NOT_FOUND
);
540 Environment
= NtCurrentPeb()->ProcessParameters
->Environment
;
544 if (Environment
== NULL
)
545 return(STATUS_VARIABLE_NOT_FOUND
);
548 if (SysEnvUsed
== TRUE
)
555 wcs
= wcschr(wcs
, L
'=');
558 wcs
= var
.Buffer
+ wcslen(var
.Buffer
);
562 var
.Length
= var
.MaximumLength
= (wcs
- var
.Buffer
) * sizeof(WCHAR
);
566 if (RtlEqualUnicodeString(&var
, Name
, TRUE
))
568 Value
->Length
= (wcs
- val
) * sizeof(WCHAR
);
569 if (Value
->Length
<= Value
->MaximumLength
)
571 memcpy(Value
->Buffer
, val
,
572 min(Value
->Length
+ sizeof(WCHAR
), Value
->MaximumLength
));
573 DPRINT("Value %S\n", val
);
574 DPRINT("Return STATUS_SUCCESS\n");
575 Status
= STATUS_SUCCESS
;
579 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
580 Status
= STATUS_BUFFER_TOO_SMALL
;
583 if (SysEnvUsed
== TRUE
)
592 if (SysEnvUsed
== TRUE
)
595 DPRINT("Return STATUS_VARIABLE_NOT_FOUND\n");
596 return(STATUS_VARIABLE_NOT_FOUND
);