ReactOS 0.4.15-dev-7924-g5949c20
env.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/env.c
5 * PURPOSE: Environment functions
6 * PROGRAMMER: Eric Kohl
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <rtl.h>
12
13#define NDEBUG
14#include <debug.h>
15
16/* FUNCTIONS *****************************************************************/
17
20RtlSetEnvironmentStrings(IN PWCHAR NewEnvironment, IN ULONG NewEnvironmentSize)
21{
24}
25
26/*
27 * @implemented
28 */
32 BOOLEAN Inherit,
33 PWSTR *OutEnvironment)
34{
36 PVOID CurrentEnvironment, NewEnvironment = NULL;
39
40 /* Check if we should inherit the current environment */
41 if (Inherit)
42 {
43 /* In this case we need to lock the PEB */
45
46 /* Get a pointer to the current Environment and check if it's not NULL */
47 CurrentEnvironment = NtCurrentPeb()->ProcessParameters->Environment;
48 if (CurrentEnvironment != NULL)
49 {
50 /* Query the size of the current environment allocation */
52 CurrentEnvironment,
54 &MemInfo,
56 NULL);
57 if (!NT_SUCCESS(Status))
58 {
60 *OutEnvironment = NULL;
61 return Status;
62 }
63
64 /* Allocate a new region of the same size */
65 RegionSize = MemInfo.RegionSize;
67 &NewEnvironment,
68 0,
72 if (!NT_SUCCESS(Status))
73 {
75 *OutEnvironment = NULL;
76 return Status;
77 }
78
79 /* Copy the current environment */
80 RtlCopyMemory(NewEnvironment,
81 CurrentEnvironment,
82 MemInfo.RegionSize);
83 }
84
85 /* We are done with the PEB, release the lock */
87 }
88
89 /* Check if we still need an environment */
90 if (NewEnvironment == NULL)
91 {
92 /* Allocate a new environment */
94 &NewEnvironment,
95 0,
99 if (NT_SUCCESS(Status))
100 {
101 RtlZeroMemory(NewEnvironment, RegionSize);
102 }
103 }
104
105 *OutEnvironment = NewEnvironment;
106
107 return Status;
108}
109
110
111/*
112 * @implemented
113 */
116{
117 SIZE_T Size = 0;
118
121 &Size,
123}
124
125
126/*
127 * @implemented
128 */
134{
135 UNICODE_STRING Variable;
137 NTSTATUS ReturnStatus = STATUS_SUCCESS;
139 PWSTR SourceBuffer;
140 PWSTR DestBuffer;
141 PWSTR CopyBuffer;
142 PWSTR VariableEnd;
143 ULONG SourceLength;
144 ULONG DestMax;
145 ULONG CopyLength;
146 ULONG Tail;
147 ULONG TotalLength = 1; /* for terminating NULL */
148
149 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
151
152 SourceLength = Source->Length / sizeof(WCHAR);
153 SourceBuffer = Source->Buffer;
154 DestMax = Destination->MaximumLength / sizeof(WCHAR);
155 DestBuffer = Destination->Buffer;
156
157 while (SourceLength)
158 {
159 if (*SourceBuffer != L'%')
160 {
161 CopyBuffer = SourceBuffer;
162 CopyLength = 0;
163 while (SourceLength != 0 && *SourceBuffer != L'%')
164 {
165 SourceBuffer++;
166 CopyLength++;
167 SourceLength--;
168 }
169 }
170 else
171 {
172 /* Process environment variable. */
173
174 VariableEnd = SourceBuffer + 1;
175 Tail = SourceLength - 1;
176 while (*VariableEnd != L'%' && Tail != 0)
177 {
178 VariableEnd++;
179 Tail--;
180 }
181
182 if (Tail != 0)
183 {
184 Variable.MaximumLength =
185 Variable.Length = (USHORT)(VariableEnd - (SourceBuffer + 1)) * sizeof(WCHAR);
186 Variable.Buffer = SourceBuffer + 1;
187
188 Value.Length = 0;
189 Value.MaximumLength = (USHORT)DestMax * sizeof(WCHAR);
190 Value.Buffer = DestBuffer;
191
193 &Value);
195 {
196 SourceBuffer = VariableEnd + 1;
197 SourceLength = Tail - 1;
198 TotalLength += Value.Length / sizeof(WCHAR);
200 {
201 DestBuffer += Value.Length / sizeof(WCHAR);
202 DestMax -= Value.Length / sizeof(WCHAR);
203 }
204 else
205 {
206 DestMax = 0;
207 ReturnStatus = STATUS_BUFFER_TOO_SMALL;
208 }
209 continue;
210 }
211 else
212 {
213 /* Variable not found. */
214 CopyBuffer = SourceBuffer;
215 CopyLength = SourceLength - Tail + 1;
216 SourceLength -= CopyLength;
217 SourceBuffer += CopyLength;
218 }
219 }
220 else
221 {
222 /* Unfinished variable name. */
223 CopyBuffer = SourceBuffer;
224 CopyLength = SourceLength;
225 SourceLength = 0;
226 }
227 }
228
229 TotalLength += CopyLength;
230 if (DestMax)
231 {
232 if (DestMax < CopyLength)
233 {
234 CopyLength = DestMax;
235 ReturnStatus = STATUS_BUFFER_TOO_SMALL;
236 }
237 RtlCopyMemory(DestBuffer, CopyBuffer, CopyLength * sizeof(WCHAR));
238 DestMax -= CopyLength;
239 DestBuffer += CopyLength;
240 }
241 }
242
243 /* NULL-terminate the buffer. */
244 if (DestMax)
245 *DestBuffer = 0;
246 else
247 ReturnStatus = STATUS_BUFFER_TOO_SMALL;
248
249 Destination->Length = (USHORT)(DestBuffer - Destination->Buffer) * sizeof(WCHAR);
250 if (Length != NULL)
251 *Length = TotalLength * sizeof(WCHAR);
252
253 DPRINT("Destination %wZ\n", Destination);
254
255 return ReturnStatus;
256}
257
258
259/*
260 * @implemented
261 */
264 PWSTR *OldEnvironment)
265{
266 PVOID EnvPtr;
267
268 DPRINT("NewEnvironment 0x%p OldEnvironment 0x%p\n",
269 NewEnvironment, OldEnvironment);
270
272
273 EnvPtr = NtCurrentPeb()->ProcessParameters->Environment;
274 NtCurrentPeb()->ProcessParameters->Environment = NewEnvironment;
275
276 if (OldEnvironment != NULL)
277 *OldEnvironment = EnvPtr;
278
280}
281
282
283/*
284 * @implemented
285 */
290{
293 size_t hole_len, new_len, env_len = 0;
294 WCHAR *new_env = 0, *env_end = 0, *wcs, *env, *val = 0, *tail = 0, *hole = 0;
295 PWSTR head = NULL;
296 SIZE_T size = 0, new_size;
297 LONG f = 1;
299
300 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
302
303 /* Variable name must not be empty */
304 if (Name->Length < sizeof(WCHAR))
306
307 /* Variable names can't contain a '=' except as a first character. */
308 for (wcs = Name->Buffer + 1;
309 wcs < Name->Buffer + (Name->Length / sizeof(WCHAR));
310 wcs++)
311 {
312 if (*wcs == L'=')
314 }
315
316 if (Environment)
317 {
318 env = *Environment;
319 }
320 else
321 {
323 env = NtCurrentPeb()->ProcessParameters->Environment;
324 }
325
326 if (env)
327 {
328 /* get environment length */
329 wcs = env_end = env;
330 do
331 {
332 env_end += wcslen(env_end) + 1;
333 }
334 while (*env_end);
335 env_end++;
336 env_len = env_end - env;
337 DPRINT("environment length %lu characters\n", env_len);
338
339 /* find where to insert */
340 while (*wcs)
341 {
342 var.Buffer = wcs++;
343 wcs = wcschr(wcs, L'=');
344 if (wcs == NULL)
345 {
346 wcs = var.Buffer + wcslen(var.Buffer);
347 }
348 if (*wcs)
349 {
350 var.Length = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR);
351 var.MaximumLength = var.Length;
352 val = ++wcs;
353 wcs += wcslen(wcs);
355 if (f >= 0)
356 {
357 if (f) /* Insert before found */
358 {
359 hole = tail = var.Buffer;
360 }
361 else /* Exact match */
362 {
363 head = var.Buffer;
364 tail = ++wcs;
365 hole = val;
366 }
367 goto found;
368 }
369 }
370 wcs++;
371 }
372 hole = tail = wcs; /* Append to environment */
373 }
374
375found:
376 if (Value != NULL && Value->Buffer != NULL)
377 {
378 hole_len = tail - hole;
379 /* calculate new environment size */
380 new_size = Value->Length + sizeof(WCHAR);
381 /* adding new variable */
382 if (f)
383 new_size += Name->Length + sizeof(WCHAR);
384 new_len = new_size / sizeof(WCHAR);
385 if (hole_len < new_len)
386 {
387 /* enlarge environment size */
388 /* check the size of available memory */
389 new_size += (env_len - hole_len) * sizeof(WCHAR);
390 new_size = ROUND_UP(new_size, PAGE_SIZE);
391 mbi.RegionSize = 0;
392 DPRINT("new_size %lu\n", new_size);
393
394 if (env)
395 {
397 env,
399 &mbi,
401 NULL);
402 if (!NT_SUCCESS(Status))
403 {
404 if (Environment == NULL)
405 {
407 }
408 return(Status);
409 }
410 }
411
412 if (new_size > mbi.RegionSize)
413 {
414 /* reallocate memory area */
416 (PVOID)&new_env,
417 0,
418 &new_size,
421 if (!NT_SUCCESS(Status))
422 {
423 if (Environment == NULL)
424 {
426 }
427 return(Status);
428 }
429
430 if (env)
431 {
432 memmove(new_env,
433 env,
434 (hole - env) * sizeof(WCHAR));
435 hole = new_env + (hole - env);
436 }
437 else
438 {
439 /* absolutely new environment */
440 tail = hole = new_env;
441 *hole = 0;
442 env_end = hole + 1;
443 }
444 }
445 }
446
447 /* move tail */
448 memmove (hole + new_len, tail, (env_end - tail) * sizeof(WCHAR));
449
450 if (new_env)
451 {
452 /* we reallocated environment, let's free the old one */
453 if (Environment)
454 *Environment = new_env;
455 else
456 NtCurrentPeb()->ProcessParameters->Environment = new_env;
457
458 if (env)
459 {
460 size = 0;
462 (PVOID)&env,
463 &size,
465 }
466 }
467
468 /* and now copy given stuff */
469 if (f)
470 {
471 /* copy variable name and '=' character */
472 memmove(hole,
473 Name->Buffer,
474 Name->Length);
475 hole += Name->Length / sizeof(WCHAR);
476 *hole++ = L'=';
477 }
478
479 /* copy value */
480 memmove(hole,
481 Value->Buffer,
482 Value->Length);
483 hole += Value->Length / sizeof(WCHAR);
484 *hole = 0;
485 }
486 else
487 {
488 /* remove the environment variable */
489 if (f == 0)
490 {
492 tail,
493 (env_end - tail) * sizeof(WCHAR));
494 }
495 }
496
497 if (Environment == NULL)
498 {
500 }
501
502 return(Status);
503}
504
505
506/*
507 * @implemented
508 */
513{
515 PWSTR wcs;
517 PWSTR val;
518 BOOLEAN SysEnvUsed = FALSE;
519
520 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
522
523 if (Environment == NULL)
524 {
526 if (Peb) {
529 SysEnvUsed = TRUE;
530 }
531 }
532
533 if (Environment == NULL)
534 {
535 if (SysEnvUsed)
538 }
539
540 Value->Length = 0;
541
543 DPRINT("Starting search at :%p\n", wcs);
544 while (*wcs)
545 {
546 var.Buffer = wcs++;
547 wcs = wcschr(wcs, L'=');
548 if (wcs == NULL)
549 {
550 wcs = var.Buffer + wcslen(var.Buffer);
551 DPRINT("Search at :%S\n", wcs);
552 }
553 if (*wcs)
554 {
555 var.Length = var.MaximumLength = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR);
556 val = ++wcs;
557 wcs += wcslen(wcs);
558 DPRINT("Search at :%S\n", wcs);
559
561 {
562 Value->Length = (USHORT)(wcs - val) * sizeof(WCHAR);
563 if (Value->Length <= Value->MaximumLength)
564 {
565 memcpy(Value->Buffer, val,
566 min(Value->Length + sizeof(WCHAR), Value->MaximumLength));
567 DPRINT("Value %S\n", val);
568 DPRINT("Return STATUS_SUCCESS\n");
570 }
571 else
572 {
573 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
575 }
576
577 if (SysEnvUsed)
579
580 return(Status);
581 }
582 }
583 wcs++;
584 }
585
586 if (SysEnvUsed)
588
589 DPRINT("Return STATUS_VARIABLE_NOT_FOUND: %wZ\n", Name);
591}
592
593/* EOF */
#define NtCurrentPeb()
Definition: FLS.c:22
unsigned char BOOLEAN
struct outqueuenode * tail
Definition: adnsresfilter.c:66
struct outqueuenode * head
Definition: adnsresfilter.c:66
LONG NTSTATUS
Definition: precomp.h:26
#define UNIMPLEMENTED
Definition: debug.h:115
Definition: bufpool.h:45
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:170
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define wcschr
Definition: compat.h:17
PPEB Peb
Definition: dllmain.c:27
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
Status
Definition: gdiplustypes.h:25
GLsizeiptr size
Definition: glext.h:5919
GLfloat f
Definition: glext.h:7540
GLuint GLfloat * val
Definition: glext.h:7180
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
NTSYSAPI void WINAPI RtlReleasePebLock(void)
Definition: libsupp.c:82
NTSYSAPI void WINAPI RtlAcquirePebLock(void)
Definition: libsupp.c:72
NTSYSAPI PEB *WINAPI RtlGetCurrentPeb(void)
Definition: libsupp.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
const char * var
Definition: shader.c:5666
#define min(a, b)
Definition: monoChain.cc:55
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
@ MemoryBasicInformation
Definition: mmtypes.h:183
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3004
#define PAGE_READWRITE
Definition: nt_native.h:1304
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define MEM_RESERVE
Definition: nt_native.h:1314
#define MEM_RELEASE
Definition: nt_native.h:1316
#define MEM_COMMIT
Definition: nt_native.h:1313
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5230
NTSTATUS NTAPI NtQueryVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN MEMORY_INFORMATION_CLASS MemoryInformationClass, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength)
Definition: virtual.c:4409
NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UBaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T URegionSize, IN ULONG AllocationType, IN ULONG Protect)
Definition: virtual.c:4492
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_VARIABLE_NOT_FOUND
Definition: ntstatus.h:492
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI RtlSetCurrentEnvironment(PWSTR NewEnvironment, PWSTR *OldEnvironment)
Definition: env.c:263
NTSTATUS NTAPI RtlExpandEnvironmentStrings_U(PWSTR Environment, PUNICODE_STRING Source, PUNICODE_STRING Destination, PULONG Length)
Definition: env.c:130
NTSTATUS NTAPI RtlCreateEnvironment(BOOLEAN Inherit, PWSTR *OutEnvironment)
Definition: env.c:31
NTSTATUS NTAPI RtlSetEnvironmentStrings(IN PWCHAR NewEnvironment, IN ULONG NewEnvironmentSize)
Definition: env.c:20
VOID NTAPI RtlDestroyEnvironment(PWSTR Environment)
Definition: env.c:115
NTSTATUS NTAPI RtlSetEnvironmentVariable(PWSTR *Environment, PUNICODE_STRING Name, PUNICODE_STRING Value)
Definition: env.c:287
NTSTATUS NTAPI RtlQueryEnvironmentVariable_U(PWSTR Environment, PCUNICODE_STRING Name, PUNICODE_STRING Value)
Definition: env.c:510
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:71
PRTL_USER_PROCESS_PARAMETERS ProcessParameters
Definition: btrfs_drv.h:1913
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ ULONG TotalLength
Definition: usbdlib.h:158
wchar_t wcs[5]
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
__wchar_t WCHAR
Definition: xmlstorage.h:180