- Revert 49767 on Pierre's request, which reverted this:
[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 * Emanuele Aliberti
9 * Thomas Weidenmueller
10 * UPDATE HISTORY:
11 * Created 01/11/98
12 */
13
14 #include <k32.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19
20 /* FUNCTIONS ******************************************************************/
21
22 /*
23 * @implemented
24 */
25 BOOL
26 WINAPI
27 Beep (DWORD dwFreq, DWORD dwDuration)
28 {
29 HANDLE hBeep;
30 UNICODE_STRING BeepDevice;
31 OBJECT_ATTRIBUTES ObjectAttributes;
32 IO_STATUS_BLOCK IoStatusBlock;
33 BEEP_SET_PARAMETERS BeepSetParameters;
34 NTSTATUS Status;
35
36 /* check the parameters */
37 if ((dwFreq >= 0x25 && dwFreq <= 0x7FFF) ||
38 (dwFreq == 0x0 && dwDuration == 0x0))
39 {
40 /* open the device */
41 RtlInitUnicodeString(&BeepDevice,
42 L"\\Device\\Beep");
43
44 InitializeObjectAttributes(&ObjectAttributes,
45 &BeepDevice,
46 0,
47 NULL,
48 NULL);
49
50 Status = NtCreateFile(&hBeep,
51 FILE_READ_DATA | FILE_WRITE_DATA,
52 &ObjectAttributes,
53 &IoStatusBlock,
54 NULL,
55 0,
56 FILE_SHARE_READ | FILE_SHARE_WRITE,
57 FILE_OPEN_IF,
58 0,
59 NULL,
60 0);
61 if (NT_SUCCESS(Status))
62 {
63 /* Set beep data */
64 BeepSetParameters.Frequency = dwFreq;
65 BeepSetParameters.Duration = dwDuration;
66
67 Status = NtDeviceIoControlFile(hBeep,
68 NULL,
69 NULL,
70 NULL,
71 &IoStatusBlock,
72 IOCTL_BEEP_SET,
73 &BeepSetParameters,
74 sizeof(BEEP_SET_PARAMETERS),
75 NULL,
76 0);
77
78 /* do an alertable wait if necessary */
79 if (NT_SUCCESS(Status) &&
80 (dwFreq != 0x0 || dwDuration != 0x0) && dwDuration != MAXDWORD)
81 {
82 SleepEx(dwDuration,
83 TRUE);
84 }
85
86 NtClose(hBeep);
87 }
88 }
89 else
90 Status = STATUS_INVALID_PARAMETER;
91
92 if (!NT_SUCCESS(Status))
93 {
94 SetLastErrorByStatus (Status);
95 return FALSE;
96 }
97
98 return TRUE;
99 }
100
101 /*
102 * @implemented
103 */
104 DWORD
105 WINAPI
106 GetEnvironmentVariableA (
107 LPCSTR lpName,
108 LPSTR lpBuffer,
109 DWORD nSize
110 )
111 {
112 ANSI_STRING VarName;
113 ANSI_STRING VarValue;
114 UNICODE_STRING VarNameU;
115 UNICODE_STRING VarValueU;
116 NTSTATUS Status;
117
118 /* initialize unicode variable name string */
119 RtlInitAnsiString (&VarName,
120 (LPSTR)lpName);
121 RtlAnsiStringToUnicodeString (&VarNameU,
122 &VarName,
123 TRUE);
124
125 /* initialize ansi variable value string */
126 VarValue.Length = 0;
127 VarValue.MaximumLength = (USHORT)nSize;
128 VarValue.Buffer = lpBuffer;
129
130 /* initialize unicode variable value string and allocate buffer */
131 VarValueU.Length = 0;
132 if (nSize != 0)
133 {
134 VarValueU.MaximumLength = (USHORT)(nSize - 1) * sizeof(WCHAR);
135 VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
136 0,
137 nSize * sizeof(WCHAR));
138 if (VarValueU.Buffer != NULL)
139 {
140 /* NULL-terminate the buffer in any case! RtlQueryEnvironmentVariable_U
141 only terminates it if MaximumLength < Length! */
142 VarValueU.Buffer[nSize - 1] = L'\0';
143 }
144 }
145 else
146 {
147 VarValueU.MaximumLength = 0;
148 VarValueU.Buffer = NULL;
149 }
150
151 if (VarValueU.Buffer != NULL || nSize == 0)
152 {
153 /* get unicode environment variable */
154 Status = RtlQueryEnvironmentVariable_U (NULL,
155 &VarNameU,
156 &VarValueU);
157 if (!NT_SUCCESS(Status))
158 {
159 /* free unicode buffer */
160 RtlFreeHeap (RtlGetProcessHeap (),
161 0,
162 VarValueU.Buffer);
163
164 /* free unicode variable name string */
165 RtlFreeUnicodeString (&VarNameU);
166
167 SetLastErrorByStatus (Status);
168 if (Status == STATUS_BUFFER_TOO_SMALL)
169 {
170 return (VarValueU.Length / sizeof(WCHAR)) + 1;
171 }
172 else
173 {
174 return 0;
175 }
176 }
177
178 /* convert unicode value string to ansi */
179 RtlUnicodeStringToAnsiString (&VarValue,
180 &VarValueU,
181 FALSE);
182
183 if (VarValueU.Buffer != NULL)
184 {
185 /* free unicode buffer */
186 RtlFreeHeap (RtlGetProcessHeap (),
187 0,
188 VarValueU.Buffer);
189 }
190
191 /* free unicode variable name string */
192 RtlFreeUnicodeString (&VarNameU);
193
194 return (VarValueU.Length / sizeof(WCHAR));
195 }
196 else
197 {
198 SetLastError (ERROR_NOT_ENOUGH_MEMORY);
199 return 0;
200 }
201 }
202
203
204 /*
205 * @implemented
206 */
207 DWORD
208 WINAPI
209 GetEnvironmentVariableW (
210 LPCWSTR lpName,
211 LPWSTR lpBuffer,
212 DWORD nSize
213 )
214 {
215 UNICODE_STRING VarName;
216 UNICODE_STRING VarValue;
217 NTSTATUS Status;
218
219 RtlInitUnicodeString (&VarName,
220 lpName);
221
222 VarValue.Length = 0;
223 VarValue.MaximumLength = (USHORT) (nSize ? nSize - 1 : 0) * sizeof(WCHAR);
224 VarValue.Buffer = lpBuffer;
225
226 Status = RtlQueryEnvironmentVariable_U (NULL,
227 &VarName,
228 &VarValue);
229 if (!NT_SUCCESS(Status))
230 {
231 if (Status == STATUS_BUFFER_TOO_SMALL)
232 {
233 return (VarValue.Length / sizeof(WCHAR)) + 1;
234 }
235 else
236 {
237 SetLastErrorByStatus (Status);
238 return 0;
239 }
240 }
241
242 if (nSize != 0)
243 {
244 /* make sure the string is NULL-terminated! RtlQueryEnvironmentVariable_U
245 only terminates it if MaximumLength < Length */
246 lpBuffer[VarValue.Length / sizeof(WCHAR)] = L'\0';
247 }
248
249 return (VarValue.Length / sizeof(WCHAR));
250 }
251
252
253 /*
254 * @implemented
255 */
256 BOOL
257 WINAPI
258 SetEnvironmentVariableA (
259 LPCSTR lpName,
260 LPCSTR lpValue
261 )
262 {
263 ANSI_STRING VarName;
264 ANSI_STRING VarValue;
265 UNICODE_STRING VarNameU;
266 UNICODE_STRING VarValueU;
267 NTSTATUS Status;
268
269 DPRINT("SetEnvironmentVariableA(Name '%s', Value '%s')\n", lpName, lpValue);
270
271 RtlInitAnsiString (&VarName,
272 (LPSTR)lpName);
273 RtlAnsiStringToUnicodeString (&VarNameU,
274 &VarName,
275 TRUE);
276
277 if (lpValue)
278 {
279 RtlInitAnsiString (&VarValue,
280 (LPSTR)lpValue);
281 RtlAnsiStringToUnicodeString (&VarValueU,
282 &VarValue,
283 TRUE);
284
285 Status = RtlSetEnvironmentVariable (NULL,
286 &VarNameU,
287 &VarValueU);
288
289 RtlFreeUnicodeString (&VarValueU);
290 }
291 else
292 {
293 Status = RtlSetEnvironmentVariable (NULL,
294 &VarNameU,
295 NULL);
296 }
297 RtlFreeUnicodeString (&VarNameU);
298
299 if (!NT_SUCCESS(Status))
300 {
301 SetLastErrorByStatus (Status);
302 return FALSE;
303 }
304
305 return TRUE;
306 }
307
308
309 /*
310 * @implemented
311 */
312 BOOL
313 WINAPI
314 SetEnvironmentVariableW (
315 LPCWSTR lpName,
316 LPCWSTR lpValue
317 )
318 {
319 UNICODE_STRING VarName;
320 UNICODE_STRING VarValue;
321 NTSTATUS Status;
322
323 DPRINT("SetEnvironmentVariableW(Name '%S', Value '%S')\n", lpName, lpValue);
324
325 RtlInitUnicodeString (&VarName,
326 lpName);
327
328 RtlInitUnicodeString (&VarValue,
329 lpValue);
330
331 Status = RtlSetEnvironmentVariable (NULL,
332 &VarName,
333 &VarValue);
334
335 if (!NT_SUCCESS(Status))
336 {
337 SetLastErrorByStatus (Status);
338 return FALSE;
339 }
340
341 return TRUE;
342 }
343
344
345 /*
346 * @implemented
347 */
348 LPSTR
349 WINAPI
350 GetEnvironmentStringsA (
351 VOID
352 )
353 {
354 UNICODE_STRING UnicodeString;
355 ANSI_STRING AnsiString;
356 PWCHAR EnvU;
357 PWCHAR PtrU;
358 ULONG Length;
359 PCHAR EnvPtr = NULL;
360
361 EnvU = (PWCHAR)(NtCurrentPeb ()->ProcessParameters->Environment);
362
363 if (EnvU == NULL)
364 return NULL;
365
366 if (*EnvU == 0)
367 return NULL;
368
369 /* get environment size */
370 PtrU = EnvU;
371 while (*PtrU)
372 {
373 while (*PtrU)
374 PtrU++;
375 PtrU++;
376 }
377 Length = (ULONG)(PtrU - EnvU);
378 DPRINT("Length %lu\n", Length);
379
380 /* allocate environment buffer */
381 EnvPtr = RtlAllocateHeap (RtlGetProcessHeap (),
382 0,
383 Length + 1);
384 if (EnvPtr == NULL)
385 {
386 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
387 return NULL;
388 }
389 DPRINT("EnvPtr %p\n", EnvPtr);
390
391 /* convert unicode environment to ansi */
392 UnicodeString.MaximumLength = (USHORT)Length * sizeof(WCHAR) + sizeof(WCHAR);
393 UnicodeString.Buffer = EnvU;
394
395 AnsiString.MaximumLength = (USHORT)Length + 1;
396 AnsiString.Length = 0;
397 AnsiString.Buffer = EnvPtr;
398
399 DPRINT ("UnicodeString.Buffer \'%S\'\n", UnicodeString.Buffer);
400
401 while (*(UnicodeString.Buffer))
402 {
403 UnicodeString.Length = wcslen (UnicodeString.Buffer) * sizeof(WCHAR);
404 UnicodeString.MaximumLength = UnicodeString.Length + sizeof(WCHAR);
405 if (UnicodeString.Length > 0)
406 {
407 AnsiString.Length = 0;
408 AnsiString.MaximumLength = (USHORT)Length + 1 - (AnsiString.Buffer - EnvPtr);
409
410 RtlUnicodeStringToAnsiString (&AnsiString,
411 &UnicodeString,
412 FALSE);
413
414 AnsiString.Buffer += (AnsiString.Length + 1);
415 UnicodeString.Buffer += ((UnicodeString.Length / sizeof(WCHAR)) + 1);
416 }
417 }
418 *(AnsiString.Buffer) = 0;
419
420 return EnvPtr;
421 }
422
423
424 /*
425 * @implemented
426 */
427 LPWSTR
428 WINAPI
429 GetEnvironmentStringsW (
430 VOID
431 )
432 {
433 return (LPWSTR)(NtCurrentPeb ()->ProcessParameters->Environment);
434 }
435
436
437 /*
438 * @implemented
439 */
440 BOOL
441 WINAPI
442 FreeEnvironmentStringsA (
443 LPSTR EnvironmentStrings
444 )
445 {
446 if (EnvironmentStrings == NULL)
447 return FALSE;
448
449 RtlFreeHeap (RtlGetProcessHeap (),
450 0,
451 EnvironmentStrings);
452
453 return TRUE;
454 }
455
456
457 /*
458 * @implemented
459 */
460 BOOL
461 WINAPI
462 FreeEnvironmentStringsW (
463 LPWSTR EnvironmentStrings
464 )
465 {
466 return TRUE;
467 }
468
469
470 /*
471 * @implemented
472 */
473 DWORD
474 WINAPI
475 ExpandEnvironmentStringsA (
476 LPCSTR lpSrc,
477 LPSTR lpDst,
478 DWORD nSize
479 )
480 {
481 ANSI_STRING Source;
482 ANSI_STRING Destination;
483 UNICODE_STRING SourceU;
484 UNICODE_STRING DestinationU;
485 NTSTATUS Status;
486 ULONG Length = 0;
487
488 RtlInitAnsiString (&Source,
489 (LPSTR)lpSrc);
490 Status = RtlAnsiStringToUnicodeString (&SourceU,
491 &Source,
492 TRUE);
493 if (!NT_SUCCESS(Status))
494 {
495 SetLastErrorByStatus (Status);
496 return 0;
497 }
498
499 /* make sure we don't overflow the maximum ANSI_STRING size */
500 if (nSize > 0x7fff)
501 nSize = 0x7fff;
502
503 Destination.Length = 0;
504 Destination.MaximumLength = (USHORT)nSize;
505 Destination.Buffer = lpDst;
506
507 DestinationU.Length = 0;
508 DestinationU.MaximumLength = (USHORT)nSize * sizeof(WCHAR);
509 DestinationU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
510 0,
511 DestinationU.MaximumLength);
512 if (DestinationU.Buffer == NULL)
513 {
514 RtlFreeUnicodeString(&SourceU);
515 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
516 return 0;
517 }
518
519 Status = RtlExpandEnvironmentStrings_U (NULL,
520 &SourceU,
521 &DestinationU,
522 &Length);
523
524 RtlFreeUnicodeString (&SourceU);
525
526 if (!NT_SUCCESS(Status))
527 {
528 SetLastErrorByStatus (Status);
529 if (Status != STATUS_BUFFER_TOO_SMALL)
530 {
531 RtlFreeHeap (RtlGetProcessHeap (),
532 0,
533 DestinationU.Buffer);
534 return 0;
535 }
536 }
537
538 RtlUnicodeStringToAnsiString (&Destination,
539 &DestinationU,
540 FALSE);
541
542 RtlFreeHeap (RtlGetProcessHeap (),
543 0,
544 DestinationU.Buffer);
545
546 return (Length / sizeof(WCHAR));
547 }
548
549
550 /*
551 * @implemented
552 */
553 DWORD
554 WINAPI
555 ExpandEnvironmentStringsW (
556 LPCWSTR lpSrc,
557 LPWSTR lpDst,
558 DWORD nSize
559 )
560 {
561 UNICODE_STRING Source;
562 UNICODE_STRING Destination;
563 NTSTATUS Status;
564 ULONG Length = 0;
565
566 RtlInitUnicodeString (&Source,
567 (LPWSTR)lpSrc);
568
569 /* make sure we don't overflow the maximum UNICODE_STRING size */
570 if (nSize > 0x7fff)
571 nSize = 0x7fff;
572
573 Destination.Length = 0;
574 Destination.MaximumLength = (USHORT)nSize * sizeof(WCHAR);
575 Destination.Buffer = lpDst;
576
577 Status = RtlExpandEnvironmentStrings_U (NULL,
578 &Source,
579 &Destination,
580 &Length);
581 if (!NT_SUCCESS(Status))
582 {
583 SetLastErrorByStatus (Status);
584 if (Status != STATUS_BUFFER_TOO_SMALL)
585 return 0;
586 }
587
588 return (Length / sizeof(WCHAR));
589 }
590
591 /* EOF */