ReactOS  0.4.13-dev-551-gf37fb1f
environ.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: dll/win32/kernel32/client/environ.c
5  * PURPOSE: Environment functions
6  * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7  * Emanuele Aliberti
8  * Thomas Weidenmueller
9  * UPDATE HISTORY:
10  * Created 01/11/98
11  */
12 
13 /* INCLUDES *******************************************************************/
14 
15 #include <k32.h>
16 
17 #define NDEBUG
18 #include <debug.h>
19 
20 /* FUNCTIONS ******************************************************************/
21 
22 /*
23  * @implemented
24  */
25 DWORD
26 WINAPI
30  IN DWORD nSize)
31 {
32  ANSI_STRING VarName, VarValue;
33  UNICODE_STRING VarNameU, VarValueU;
34  PWSTR Buffer;
35  ULONG Result = 0;
36  USHORT UniSize;
38 
39  /* Initialize all the strings */
40  RtlInitAnsiString(&VarName, lpName);
41  RtlInitUnicodeString(&VarNameU, NULL);
42  RtlInitUnicodeString(&VarValueU, NULL);
43  Status = RtlAnsiStringToUnicodeString(&VarNameU, &VarName, TRUE);
44  if (!NT_SUCCESS(Status)) goto Quickie;
45 
46  /* Check if the size is too big to fit */
47  UniSize = UNICODE_STRING_MAX_CHARS - 2;
48  if (nSize <= UniSize)
49  {
50  /* It fits, but was there a string at all? */
51  if (nSize)
52  {
53  /* Keep the given size, minus a NULL-char */
54  UniSize = (USHORT)(nSize - 1);
55  }
56  else
57  {
58  /* No size */
59  UniSize = 0;
60  }
61  }
62  else
63  {
64  /* String is too big, so we need to return a NULL char as well */
65  UniSize--;
66  }
67 
68  /* Allocate the value string buffer */
69  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize * sizeof(WCHAR));
70  if (!Buffer)
71  {
73  goto Quickie;
74  }
75 
76  /* And initialize its string */
77  RtlInitEmptyUnicodeString(&VarValueU, Buffer, UniSize * sizeof(WCHAR));
78 
79  /* Acquire the PEB lock since we'll be querying variables now */
81 
82  /* Query the variable */
83  Status = RtlQueryEnvironmentVariable_U(NULL, &VarNameU, &VarValueU);
85 
86  /* Check if we didn't have enough space */
88  {
89  /* Fixup the length that the API returned */
90  VarValueU.MaximumLength = VarValueU.Length + sizeof(UNICODE_NULL);
91 
92  /* Free old Unicode buffer */
93  RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU.Buffer);
94 
95  /* Allocate new one */
96  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, VarValueU.MaximumLength);
97  if (Buffer)
98  {
99  /* Query the variable so we can know its size */
100  VarValueU.Buffer = Buffer;
101  Status = RtlQueryEnvironmentVariable_U(NULL, &VarNameU, &VarValueU);
102  if (NT_SUCCESS(Status))
103  {
104  /* Get the ASCII length of the variable */
105  Result = RtlUnicodeStringToAnsiSize(&VarValueU);
106  }
107  }
108  else
109  {
110  /* Set failure status */
112  VarValueU.Buffer = NULL;
113  }
114  }
115  else if (NT_SUCCESS(Status))
116  {
117  /* Check if the size is too big to fit */
118  UniSize = UNICODE_STRING_MAX_BYTES - 1;
119  if (nSize <= UniSize) UniSize = (USHORT)nSize;
120 
121  /* Check the size */
122  Result = RtlUnicodeStringToAnsiSize(&VarValueU);
123  if (Result <= UniSize)
124  {
125  /* Convert the string */
126  RtlInitEmptyAnsiString(&VarValue, lpBuffer, UniSize);
127  Status = RtlUnicodeStringToAnsiString(&VarValue, &VarValueU, FALSE);
128  if (NT_SUCCESS(Status))
129  {
130  /* NULL-terminate and set the final length */
131  lpBuffer[VarValue.Length] = ANSI_NULL;
132  Result = VarValue.Length;
133  }
134  }
135  }
136 
137  /* Release the lock */
139 
140 Quickie:
141  /* Free the strings */
142  RtlFreeUnicodeString(&VarNameU);
143  if (VarValueU.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU.Buffer);
144 
145  /* Check if we succeeded */
146  if (!NT_SUCCESS(Status))
147  {
148  /* We did not, clear the result and set the error code */
150  Result = 0;
151  }
152 
153  /* Return the result */
154  return Result;
155 }
156 
157 /*
158  * @implemented
159  */
160 DWORD
161 WINAPI
165  IN DWORD nSize)
166 {
167  UNICODE_STRING VarName, VarValue;
169  USHORT UniSize;
170 
171  if (nSize <= (UNICODE_STRING_MAX_CHARS - 1))
172  {
173  if (nSize)
174  {
175  UniSize = (USHORT)nSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
176  }
177  else
178  {
179  UniSize = 0;
180  }
181  }
182  else
183  {
184  UniSize = UNICODE_STRING_MAX_BYTES - sizeof(UNICODE_NULL);
185  }
186 
187  Status = RtlInitUnicodeStringEx(&VarName, lpName);
188  if (!NT_SUCCESS(Status))
189  {
191  return 0;
192  }
193 
194  RtlInitEmptyUnicodeString(&VarValue, lpBuffer, UniSize);
195 
196  Status = RtlQueryEnvironmentVariable_U(NULL, &VarName, &VarValue);
197  if (!NT_SUCCESS(Status))
198  {
200  {
201  return (VarValue.Length / sizeof(WCHAR)) + sizeof(ANSI_NULL);
202  }
204  return 0;
205  }
206 
207  lpBuffer[VarValue.Length / sizeof(WCHAR)] = UNICODE_NULL;
208 
209  return (VarValue.Length / sizeof(WCHAR));
210 }
211 
212 /*
213  * @implemented
214  */
215 BOOL
216 WINAPI
219  IN LPCSTR lpValue)
220 {
221  ANSI_STRING VarName, VarValue;
222  UNICODE_STRING VarNameU, VarValueU;
224 
225  RtlInitAnsiString(&VarName, (LPSTR)lpName);
226  Status = RtlAnsiStringToUnicodeString(&VarNameU, &VarName, TRUE);
227  if (NT_SUCCESS(Status))
228  {
229  if (lpValue)
230  {
231  RtlInitAnsiString(&VarValue, (LPSTR)lpValue);
232  Status = RtlAnsiStringToUnicodeString(&VarValueU, &VarValue, TRUE);
233  if (NT_SUCCESS(Status))
234  {
235  Status = RtlSetEnvironmentVariable(NULL, &VarNameU, &VarValueU);
236  RtlFreeUnicodeString(&VarValueU);
237  }
238  }
239  else
240  {
241  Status = RtlSetEnvironmentVariable(NULL, &VarNameU, NULL);
242  }
243 
244  RtlFreeUnicodeString(&VarNameU);
245 
246  if (NT_SUCCESS(Status)) return TRUE;
247  }
248 
250  return FALSE;
251 }
252 
253 /*
254  * @implemented
255  */
256 BOOL
257 WINAPI
260  IN LPCWSTR lpValue)
261 {
262  UNICODE_STRING VarName, VarValue;
264 
265  Status = RtlInitUnicodeStringEx(&VarName, lpName);
266  if (NT_SUCCESS(Status))
267  {
268  if (lpValue)
269  {
270  Status = RtlInitUnicodeStringEx(&VarValue, lpValue);
271  if (NT_SUCCESS(Status))
272  {
273  Status = RtlSetEnvironmentVariable(NULL, &VarName, &VarValue);
274  }
275  }
276  else
277  {
279  }
280 
281  if (NT_SUCCESS(Status)) return TRUE;
282  }
283 
285  return FALSE;
286 }
287 
288 /*
289  * @implemented
290  */
291 LPSTR
292 WINAPI
294 {
295  ULONG Length, Size;
298  PCHAR Buffer = NULL;
299 
301  p = Environment = NtCurrentPeb()->ProcessParameters->Environment;
302 
303  do
304  {
305  p += wcslen(p) + 1;
306  } while (*p);
307 
308  Length = p - Environment + 1;
309 
311  if (NT_SUCCESS(Status))
312  {
313  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
314  if (Buffer)
315  {
317  if (!NT_SUCCESS(Status))
318  {
319  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
320  Buffer = NULL;
321 
323  }
324  }
325  else
326  {
328  }
329  }
330  else
331  {
333  }
334 
336  return Buffer;
337 }
338 
339 /*
340  * @implemented
341  */
342 LPWSTR
343 WINAPI
345 {
347  ULONG Length;
348 
350 
351  p = Environment = NtCurrentPeb()->ProcessParameters->Environment;
352 
353  do
354  {
355  p += wcslen(p) + 1;
356  } while (*p);
357 
358  Length = p - Environment + 1;
359 
360  p = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
361  if (p)
362  {
363  RtlCopyMemory(p, Environment, Length * sizeof(WCHAR));
364  }
365  else
366  {
368  }
369 
371  return p;
372 }
373 
374 /*
375  * @implemented
376  */
377 BOOL
378 WINAPI
379 FreeEnvironmentStringsA(IN LPSTR EnvironmentStrings)
380 {
381  return RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings);
382 }
383 
384 /*
385  * @implemented
386  */
387 BOOL
388 WINAPI
389 FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings)
390 {
391  return RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings);
392 }
393 
394 /*
395  * @implemented
396  */
397 DWORD
398 WINAPI
400  IN LPSTR lpDst,
401  IN DWORD nSize)
402 {
403  ANSI_STRING Source, Dest;
404  UNICODE_STRING SourceU, DestU;
405  PWSTR Buffer;
406  ULONG Result = 0, Length;
407  USHORT UniSize;
409 
410  /* Check if the size is too big to fit */
411  UniSize = UNICODE_STRING_MAX_CHARS - 2;
412  if (nSize <= UniSize) UniSize = (USHORT)nSize;
413 
414  /* Clear the input buffer */
415  if (lpDst) *lpDst = ANSI_NULL;
416 
417  /* Initialize all the strings */
418  RtlInitAnsiString(&Source, lpSrc);
419  RtlInitUnicodeString(&SourceU, NULL);
420  RtlInitUnicodeString(&DestU, NULL);
422  if (!NT_SUCCESS(Status)) goto Quickie;
423 
424  /* If the string fit in, make space for a NULL char */
425  if (UniSize)
426  {
427  UniSize--;
428  }
429  else
430  {
431  /* No input size, so no string size */
432  UniSize = 0;
433  }
434 
435  /* Allocate the value string buffer */
436  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize * sizeof(WCHAR));
437  if (!Buffer)
438  {
440  goto Quickie;
441  }
442 
443  /* And initialize its string */
444  RtlInitEmptyUnicodeString(&DestU, Buffer, UniSize * sizeof(WCHAR));
445 
446  /* Query the variable */
447  Length = 0;
448  Status = RtlExpandEnvironmentStrings_U(NULL, &SourceU, &DestU, &Length);
449 
450  /* Check if we didn't have enough space */
452  {
453  /* Fixup the length that the API returned */
454  DestU.MaximumLength = (SHORT)Length;
455 
456  /* Free old Unicode buffer */
457  RtlFreeHeap(RtlGetProcessHeap(), 0, DestU.Buffer);
458 
459  /* Allocate new one */
460  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
461  if (Buffer)
462  {
463  /* Query the variable so we can know its size */
464  DestU.Buffer = Buffer;
465  Status = RtlExpandEnvironmentStrings_U(NULL, &SourceU, &DestU, &Length);
466  if (NT_SUCCESS(Status))
467  {
468  /* Get the ASCII length of the variable, add a byte for NULL */
469  Result = RtlUnicodeStringToAnsiSize(&DestU) + sizeof(ANSI_NULL);
470  }
471  }
472  else
473  {
474  /* Set failure status */
476  DestU.Buffer = NULL;
477  }
478  }
479  else if (NT_SUCCESS(Status))
480  {
481  /* Check if the size is too big to fit */
482  UniSize = UNICODE_STRING_MAX_BYTES - 1;
483  if (nSize <= UniSize) UniSize = (USHORT)nSize;
484 
485  /* Check the size */
487  if (Result <= UniSize)
488  {
489  /* Convert the string */
490  RtlInitEmptyAnsiString(&Dest, lpDst, UniSize);
491  Status = RtlUnicodeStringToAnsiString(&Dest, &DestU, FALSE);
492 
493  /* Write a NULL-char in case of failure only */
494  if (!NT_SUCCESS(Status)) *lpDst = ANSI_NULL;
495  }
496  }
497 Quickie:
498  /* Free the strings */
499  RtlFreeUnicodeString(&SourceU);
500  if (DestU.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, DestU.Buffer);
501 
502  /* Check if we succeeded */
503  if (!NT_SUCCESS(Status))
504  {
505  /* We did not, clear the result and set the error code */
507  Result = 0;
508  }
509 
510  /* Return the result */
511  return Result;
512 }
513 
514 /*
515  * @implemented
516  */
517 DWORD
518 WINAPI
520  IN LPWSTR lpDst,
521  IN DWORD nSize)
522 {
525  USHORT UniSize;
526 
527  UniSize = min(nSize, UNICODE_STRING_MAX_CHARS - 2);
528 
530  RtlInitEmptyUnicodeString(&Destination, lpDst, UniSize * sizeof(WCHAR));
531 
533  &Source,
534  &Destination,
535  &nSize);
537  {
538  return nSize / sizeof(WCHAR);
539  }
540 
542  return 0;
543 }
544 
545 /*
546  * @implemented
547  */
548 BOOL
549 WINAPI
551 {
552  STUB;
553  return FALSE;
554 }
555 
556 /*
557  * @implemented
558  */
559 BOOL
560 WINAPI
562 {
563  STUB;
564  return FALSE;
565 }
566 
567 /* EOF */
signed char * PCHAR
Definition: retypes.h:7
BOOL WINAPI SetEnvironmentStringsW(IN LPWCH NewEnvironment)
Definition: environ.c:561
DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableW(IN LPCWSTR lpName, IN LPWSTR lpBuffer, IN DWORD nSize)
Definition: environ.c:163
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:45
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
NTSYSAPI DWORD WINAPI RtlUnicodeStringToAnsiSize(const UNICODE_STRING *)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:54
NTSYSAPI NTSTATUS NTAPI RtlUnicodeToMultiByteSize(PULONG MbSize, PCWCH UnicodeString, ULONG UnicodeSize)
LONG NTSTATUS
Definition: precomp.h:26
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:2024
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
_In_ LPCSTR lpName
Definition: winbase.h:2729
BOOL WINAPI FreeEnvironmentStringsA(IN LPSTR EnvironmentStrings)
Definition: environ.c:379
VOID NTAPI RtlReleasePebLock(VOID)
Definition: libsupp.c:82
uint16_t * PWCHAR
Definition: typedefs.h:54
char * LPSTR
Definition: xmlstorage.h:182
#define UNICODE_STRING_MAX_BYTES
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define UNICODE_NULL
#define ANSI_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
NTSYSAPI NTSTATUS NTAPI RtlUnicodeToOemN(PCHAR OemString, ULONG OemSize, PULONG ResultSize, PCWCH UnicodeString, ULONG UnicodeSize)
short SHORT
Definition: pedump.c:59
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:173
NTSYSAPI NTSTATUS NTAPI RtlQueryEnvironmentVariable_U(_In_opt_ PWSTR Environment, _In_ PCUNICODE_STRING Name, _Out_ PUNICODE_STRING Value)
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
NTSYSAPI NTSTATUS NTAPI RtlSetEnvironmentVariable(_In_z_ PWSTR *Environment, _In_ PUNICODE_STRING Name, _In_ PUNICODE_STRING Value)
DWORD WINAPI ExpandEnvironmentStringsA(IN LPCSTR lpSrc, IN LPSTR lpDst, IN DWORD nSize)
Definition: environ.c:399
Definition: bufpool.h:45
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
const char * LPCSTR
Definition: xmlstorage.h:183
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
NTSYSAPI NTSTATUS WINAPI RtlExpandEnvironmentStrings_U(PCWSTR, const UNICODE_STRING *, UNICODE_STRING *, ULONG *)
#define DECLSPEC_HOTPATCH
Definition: _mingw.h:240
#define UNICODE_STRING_MAX_CHARS
BOOL WINAPI FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings)
Definition: environ.c:389
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA(IN LPCSTR lpName, IN LPCSTR lpValue)
Definition: environ.c:218
#define WINAPI
Definition: msvc.h:8
CHAR * LPCH
Definition: ntbasedef.h:398
unsigned long DWORD
Definition: ntddk_ex.h:95
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:2875
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW(IN LPCWSTR lpName, IN LPCWSTR lpValue)
Definition: environ.c:259
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
LPSTR WINAPI GetEnvironmentStringsA(VOID)
Definition: environ.c:293
Status
Definition: gdiplustypes.h:24
#define NtCurrentPeb()
Definition: FLS.c:20
#define STUB
Definition: kernel32.h:27
unsigned short USHORT
Definition: pedump.c:61
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define min(a, b)
Definition: monoChain.cc:55
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
VOID NTAPI RtlAcquirePebLock(VOID)
Definition: libsupp.c:72
LPWSTR WINAPI GetEnvironmentStringsW(VOID)
Definition: environ.c:344
BOOL WINAPI SetEnvironmentStringsA(IN LPCH NewEnvironment)
Definition: environ.c:550
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3167
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
WCHAR * LPWCH
Definition: ntbasedef.h:417
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableA(IN LPCSTR lpName, IN LPSTR lpBuffer, IN DWORD nSize)
Definition: environ.c:28
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)