reshuffling of dlls
[reactos.git] / reactos / dll / win32 / kernel32 / misc / env.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/env.c
6 * PURPOSE: Environment functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 #include <k32.h>
13
14 #define NDEBUG
15 #include "../include/debug.h"
16
17
18 /* FUNCTIONS ******************************************************************/
19
20 /*
21 * @implemented
22 */
23 DWORD
24 STDCALL
25 GetEnvironmentVariableA (
26 LPCSTR lpName,
27 LPSTR lpBuffer,
28 DWORD nSize
29 )
30 {
31 ANSI_STRING VarName;
32 ANSI_STRING VarValue;
33 UNICODE_STRING VarNameU;
34 UNICODE_STRING VarValueU;
35 NTSTATUS Status;
36
37 /* initialize unicode variable name string */
38 RtlInitAnsiString (&VarName,
39 (LPSTR)lpName);
40 RtlAnsiStringToUnicodeString (&VarNameU,
41 &VarName,
42 TRUE);
43
44 /* initialize ansi variable value string */
45 VarValue.Length = 0;
46 VarValue.MaximumLength = nSize;
47 VarValue.Buffer = lpBuffer;
48
49 /* initialize unicode variable value string and allocate buffer */
50 VarValueU.Length = 0;
51 if (nSize != 0)
52 {
53 VarValueU.MaximumLength = (nSize - 1) * sizeof(WCHAR);
54 VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
55 0,
56 nSize * sizeof(WCHAR));
57 if (VarValueU.Buffer != NULL)
58 {
59 /* NULL-terminate the buffer in any case! RtlQueryEnvironmentVariable_U
60 only terminates it if MaximumLength < Length! */
61 VarValueU.Buffer[nSize - 1] = L'\0';
62 }
63 }
64 else
65 {
66 VarValueU.MaximumLength = 0;
67 VarValueU.Buffer = NULL;
68 }
69
70 if (VarValueU.Buffer != NULL || nSize == 0)
71 {
72 /* get unicode environment variable */
73 Status = RtlQueryEnvironmentVariable_U (NULL,
74 &VarNameU,
75 &VarValueU);
76 if (!NT_SUCCESS(Status))
77 {
78 /* free unicode buffer */
79 RtlFreeHeap (RtlGetProcessHeap (),
80 0,
81 VarValueU.Buffer);
82
83 /* free unicode variable name string */
84 RtlFreeUnicodeString (&VarNameU);
85
86 SetLastErrorByStatus (Status);
87 if (Status == STATUS_BUFFER_TOO_SMALL)
88 {
89 return (VarValueU.Length / sizeof(WCHAR)) + 1;
90 }
91 else
92 {
93 return 0;
94 }
95 }
96
97 /* convert unicode value string to ansi */
98 RtlUnicodeStringToAnsiString (&VarValue,
99 &VarValueU,
100 FALSE);
101
102 if (VarValueU.Buffer != NULL)
103 {
104 /* free unicode buffer */
105 RtlFreeHeap (RtlGetProcessHeap (),
106 0,
107 VarValueU.Buffer);
108 }
109
110 /* free unicode variable name string */
111 RtlFreeUnicodeString (&VarNameU);
112
113 return (VarValueU.Length / sizeof(WCHAR));
114 }
115 else
116 {
117 SetLastError (ERROR_NOT_ENOUGH_MEMORY);
118 return 0;
119 }
120 }
121
122
123 /*
124 * @implemented
125 */
126 DWORD
127 STDCALL
128 GetEnvironmentVariableW (
129 LPCWSTR lpName,
130 LPWSTR lpBuffer,
131 DWORD nSize
132 )
133 {
134 UNICODE_STRING VarName;
135 UNICODE_STRING VarValue;
136 NTSTATUS Status;
137
138 RtlInitUnicodeString (&VarName,
139 lpName);
140
141 VarValue.Length = 0;
142 VarValue.MaximumLength = (nSize != 0 ? (nSize - 1) * sizeof(WCHAR) : 0);
143 VarValue.Buffer = lpBuffer;
144
145 Status = RtlQueryEnvironmentVariable_U (NULL,
146 &VarName,
147 &VarValue);
148 if (!NT_SUCCESS(Status))
149 {
150 SetLastErrorByStatus (Status);
151 if (Status == STATUS_BUFFER_TOO_SMALL)
152 {
153 return (VarValue.Length / sizeof(WCHAR)) + 1;
154 }
155 else
156 {
157 return 0;
158 }
159 }
160
161 if (nSize != 0)
162 {
163 /* make sure the string is NULL-terminated! RtlQueryEnvironmentVariable_U
164 only terminates it if MaximumLength < Length */
165 VarValue.Buffer[VarValue.Length / sizeof(WCHAR)] = L'\0';
166 }
167
168 return (VarValue.Length / sizeof(WCHAR));
169 }
170
171
172 /*
173 * @implemented
174 */
175 BOOL
176 STDCALL
177 SetEnvironmentVariableA (
178 LPCSTR lpName,
179 LPCSTR lpValue
180 )
181 {
182 ANSI_STRING VarName;
183 ANSI_STRING VarValue;
184 UNICODE_STRING VarNameU;
185 UNICODE_STRING VarValueU;
186 NTSTATUS Status;
187
188 DPRINT("SetEnvironmentVariableA(Name '%s', Value '%s')\n", lpName, lpValue);
189
190 RtlInitAnsiString (&VarName,
191 (LPSTR)lpName);
192 RtlAnsiStringToUnicodeString (&VarNameU,
193 &VarName,
194 TRUE);
195
196 RtlInitAnsiString (&VarValue,
197 (LPSTR)lpValue);
198 RtlAnsiStringToUnicodeString (&VarValueU,
199 &VarValue,
200 TRUE);
201
202 Status = RtlSetEnvironmentVariable (NULL,
203 &VarNameU,
204 &VarValueU);
205
206 RtlFreeUnicodeString (&VarNameU);
207 RtlFreeUnicodeString (&VarValueU);
208
209 if (!NT_SUCCESS(Status))
210 {
211 SetLastErrorByStatus (Status);
212 return FALSE;
213 }
214
215 return TRUE;
216 }
217
218
219 /*
220 * @implemented
221 */
222 BOOL
223 STDCALL
224 SetEnvironmentVariableW (
225 LPCWSTR lpName,
226 LPCWSTR lpValue
227 )
228 {
229 UNICODE_STRING VarName;
230 UNICODE_STRING VarValue;
231 NTSTATUS Status;
232
233 DPRINT("SetEnvironmentVariableW(Name '%S', Value '%S')\n", lpName, lpValue);
234
235 RtlInitUnicodeString (&VarName,
236 lpName);
237
238 RtlInitUnicodeString (&VarValue,
239 lpValue);
240
241 Status = RtlSetEnvironmentVariable (NULL,
242 &VarName,
243 &VarValue);
244 if (!NT_SUCCESS(Status))
245 {
246 SetLastErrorByStatus (Status);
247 return FALSE;
248 }
249
250 return TRUE;
251 }
252
253
254 /*
255 * @implemented
256 */
257 LPSTR
258 STDCALL
259 GetEnvironmentStringsA (
260 VOID
261 )
262 {
263 UNICODE_STRING UnicodeString;
264 ANSI_STRING AnsiString;
265 PWCHAR EnvU;
266 PWCHAR PtrU;
267 ULONG Length;
268 PCHAR EnvPtr = NULL;
269
270 EnvU = (PWCHAR)(NtCurrentPeb ()->ProcessParameters->Environment);
271
272 if (EnvU == NULL)
273 return NULL;
274
275 if (*EnvU == 0)
276 return NULL;
277
278 /* get environment size */
279 PtrU = EnvU;
280 while (*PtrU)
281 {
282 while (*PtrU)
283 PtrU++;
284 PtrU++;
285 }
286 Length = (ULONG)(PtrU - EnvU);
287 DPRINT("Length %lu\n", Length);
288
289 /* allocate environment buffer */
290 EnvPtr = RtlAllocateHeap (RtlGetProcessHeap (),
291 0,
292 Length + 1);
293 if (EnvPtr == NULL)
294 {
295 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
296 return NULL;
297 }
298 DPRINT("EnvPtr %p\n", EnvPtr);
299
300 /* convert unicode environment to ansi */
301 UnicodeString.MaximumLength = Length * sizeof(WCHAR) + sizeof(WCHAR);
302 UnicodeString.Buffer = EnvU;
303
304 AnsiString.MaximumLength = Length + 1;
305 AnsiString.Length = 0;
306 AnsiString.Buffer = EnvPtr;
307
308 DPRINT ("UnicodeString.Buffer \'%S\'\n", UnicodeString.Buffer);
309
310 while (*(UnicodeString.Buffer))
311 {
312 UnicodeString.Length = wcslen (UnicodeString.Buffer) * sizeof(WCHAR);
313 UnicodeString.MaximumLength = UnicodeString.Length + sizeof(WCHAR);
314 if (UnicodeString.Length > 0)
315 {
316 AnsiString.Length = 0;
317 AnsiString.MaximumLength = Length + 1 - (AnsiString.Buffer - EnvPtr);
318
319 RtlUnicodeStringToAnsiString (&AnsiString,
320 &UnicodeString,
321 FALSE);
322
323 AnsiString.Buffer += (AnsiString.Length + 1);
324 UnicodeString.Buffer += ((UnicodeString.Length / sizeof(WCHAR)) + 1);
325 }
326 }
327 *(AnsiString.Buffer) = 0;
328
329 return EnvPtr;
330 }
331
332
333 /*
334 * @implemented
335 */
336 LPWSTR
337 STDCALL
338 GetEnvironmentStringsW (
339 VOID
340 )
341 {
342 return (LPWSTR)(NtCurrentPeb ()->ProcessParameters->Environment);
343 }
344
345
346 /*
347 * @implemented
348 */
349 BOOL
350 STDCALL
351 FreeEnvironmentStringsA (
352 LPSTR EnvironmentStrings
353 )
354 {
355 if (EnvironmentStrings == NULL)
356 return FALSE;
357
358 RtlFreeHeap (RtlGetProcessHeap (),
359 0,
360 EnvironmentStrings);
361
362 return TRUE;
363 }
364
365
366 /*
367 * @implemented
368 */
369 BOOL
370 STDCALL
371 FreeEnvironmentStringsW (
372 LPWSTR EnvironmentStrings
373 )
374 {
375 (void)EnvironmentStrings;
376 return TRUE;
377 }
378
379
380 /*
381 * @implemented
382 */
383 DWORD
384 STDCALL
385 ExpandEnvironmentStringsA (
386 LPCSTR lpSrc,
387 LPSTR lpDst,
388 DWORD nSize
389 )
390 {
391 ANSI_STRING Source;
392 ANSI_STRING Destination;
393 UNICODE_STRING SourceU;
394 UNICODE_STRING DestinationU;
395 NTSTATUS Status;
396 ULONG Length = 0;
397
398 RtlInitAnsiString (&Source,
399 (LPSTR)lpSrc);
400 Status = RtlAnsiStringToUnicodeString (&SourceU,
401 &Source,
402 TRUE);
403 if (!NT_SUCCESS(Status))
404 {
405 SetLastErrorByStatus (Status);
406 return 0;
407 }
408
409 Destination.Length = 0;
410 Destination.MaximumLength = nSize;
411 Destination.Buffer = lpDst;
412
413 DestinationU.Length = 0;
414 DestinationU.MaximumLength = nSize * sizeof(WCHAR);
415 DestinationU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
416 0,
417 DestinationU.MaximumLength);
418 if (DestinationU.Buffer == NULL)
419 {
420 RtlFreeUnicodeString(&SourceU);
421 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
422 return 0;
423 }
424
425 Status = RtlExpandEnvironmentStrings_U (NULL,
426 &SourceU,
427 &DestinationU,
428 &Length);
429
430 RtlFreeUnicodeString (&SourceU);
431
432 if (!NT_SUCCESS(Status))
433 {
434 SetLastErrorByStatus (Status);
435 if (Status != STATUS_BUFFER_TOO_SMALL)
436 {
437 RtlFreeHeap (RtlGetProcessHeap (),
438 0,
439 DestinationU.Buffer);
440 return 0;
441 }
442 }
443
444 RtlUnicodeStringToAnsiString (&Destination,
445 &DestinationU,
446 FALSE);
447
448 RtlFreeHeap (RtlGetProcessHeap (),
449 0,
450 DestinationU.Buffer);
451
452 return (Length / sizeof(WCHAR));
453 }
454
455
456 /*
457 * @implemented
458 */
459 DWORD
460 STDCALL
461 ExpandEnvironmentStringsW (
462 LPCWSTR lpSrc,
463 LPWSTR lpDst,
464 DWORD nSize
465 )
466 {
467 UNICODE_STRING Source;
468 UNICODE_STRING Destination;
469 NTSTATUS Status;
470 ULONG Length = 0;
471
472 RtlInitUnicodeString (&Source,
473 (LPWSTR)lpSrc);
474
475 Destination.Length = 0;
476 Destination.MaximumLength = nSize * sizeof(WCHAR);
477 Destination.Buffer = lpDst;
478
479 Status = RtlExpandEnvironmentStrings_U (NULL,
480 &Source,
481 &Destination,
482 &Length);
483 if (!NT_SUCCESS(Status))
484 {
485 SetLastErrorByStatus (Status);
486 if (Status != STATUS_BUFFER_TOO_SMALL)
487 return 0;
488 }
489
490 return (Length / sizeof(WCHAR));
491 }
492
493 /* EOF */