[KERNEL32] Initial implementation for BaseCheckRunApp, calling into apphelp to check...
[reactos.git] / reactos / dll / win32 / kernel32 / client / environ.c
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
27 DECLSPEC_HOTPATCH
28 GetEnvironmentVariableA(IN LPCSTR lpName,
29 IN LPSTR lpBuffer,
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;
37 NTSTATUS Status;
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 {
72 Status = STATUS_NO_MEMORY;
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 */
80 RtlAcquirePebLock();
81
82 /* Query the variable */
83 Status = RtlQueryEnvironmentVariable_U(NULL, &VarNameU, &VarValueU);
84 if ((NT_SUCCESS(Status)) && !(nSize)) Status = STATUS_BUFFER_TOO_SMALL;
85
86 /* Check if we didn't have enough space */
87 if (Status == STATUS_BUFFER_TOO_SMALL)
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 */
111 Status = STATUS_NO_MEMORY;
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 */
138 RtlReleasePebLock();
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 */
149 BaseSetLastNTError(Status);
150 Result = 0;
151 }
152
153 /* Return the result */
154 return Result;
155 }
156
157 /*
158 * @implemented
159 */
160 DWORD
161 WINAPI
162 DECLSPEC_HOTPATCH
163 GetEnvironmentVariableW(IN LPCWSTR lpName,
164 IN LPWSTR lpBuffer,
165 IN DWORD nSize)
166 {
167 UNICODE_STRING VarName, VarValue;
168 NTSTATUS Status;
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 {
190 BaseSetLastNTError(Status);
191 return 0;
192 }
193
194 RtlInitEmptyUnicodeString(&VarValue, lpBuffer, UniSize);
195
196 Status = RtlQueryEnvironmentVariable_U(NULL, &VarName, &VarValue);
197 if (!NT_SUCCESS(Status))
198 {
199 if (Status == STATUS_BUFFER_TOO_SMALL)
200 {
201 return (VarValue.Length / sizeof(WCHAR)) + sizeof(ANSI_NULL);
202 }
203 BaseSetLastNTError (Status);
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
217 DECLSPEC_HOTPATCH
218 SetEnvironmentVariableA(IN LPCSTR lpName,
219 IN LPCSTR lpValue)
220 {
221 ANSI_STRING VarName, VarValue;
222 UNICODE_STRING VarNameU, VarValueU;
223 NTSTATUS Status;
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
249 BaseSetLastNTError(Status);
250 return FALSE;
251 }
252
253 /*
254 * @implemented
255 */
256 BOOL
257 WINAPI
258 DECLSPEC_HOTPATCH
259 SetEnvironmentVariableW(IN LPCWSTR lpName,
260 IN LPCWSTR lpValue)
261 {
262 UNICODE_STRING VarName, VarValue;
263 NTSTATUS Status;
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 {
278 Status = RtlSetEnvironmentVariable(NULL, &VarName, NULL);
279 }
280
281 if (NT_SUCCESS(Status)) return TRUE;
282 }
283
284 BaseSetLastNTError(Status);
285 return FALSE;
286 }
287
288 /*
289 * @implemented
290 */
291 LPSTR
292 WINAPI
293 GetEnvironmentStringsA(VOID)
294 {
295 ULONG Length, Size;
296 NTSTATUS Status;
297 PWCHAR Environment, p;
298 PCHAR Buffer = NULL;
299
300 RtlAcquirePebLock();
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
310 Status = RtlUnicodeToMultiByteSize(&Size, Environment, Length * sizeof(WCHAR));
311 if (NT_SUCCESS(Status))
312 {
313 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
314 if (Buffer)
315 {
316 Status = RtlUnicodeToOemN(Buffer, Size, 0, Environment, Length * sizeof(WCHAR));
317 if (!NT_SUCCESS(Status))
318 {
319 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
320 Buffer = NULL;
321
322 BaseSetLastNTError(Status);
323 }
324 }
325 else
326 {
327 BaseSetLastNTError(STATUS_NO_MEMORY);
328 }
329 }
330 else
331 {
332 BaseSetLastNTError(Status);
333 }
334
335 RtlReleasePebLock();
336 return Buffer;
337 }
338
339 /*
340 * @implemented
341 */
342 LPWSTR
343 WINAPI
344 GetEnvironmentStringsW(VOID)
345 {
346 PWCHAR Environment, p;
347 ULONG Length;
348
349 RtlAcquirePebLock();
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 {
367 BaseSetLastNTError(STATUS_NO_MEMORY);
368 }
369
370 RtlReleasePebLock();
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
399 ExpandEnvironmentStringsA(IN LPCSTR lpSrc,
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;
408 NTSTATUS Status;
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);
421 Status = RtlAnsiStringToUnicodeString(&SourceU, &Source, TRUE);
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 {
439 Status = STATUS_NO_MEMORY;
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 */
451 if (Status == STATUS_BUFFER_TOO_SMALL)
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 */
475 Status = STATUS_NO_MEMORY;
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 */
486 Result = RtlUnicodeStringToAnsiSize(&DestU);
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 */
506 BaseSetLastNTError(Status);
507 Result = 0;
508 }
509
510 /* Return the result */
511 return Result;
512 }
513
514 /*
515 * @implemented
516 */
517 DWORD
518 WINAPI
519 ExpandEnvironmentStringsW(IN LPCWSTR lpSrc,
520 IN LPWSTR lpDst,
521 IN DWORD nSize)
522 {
523 UNICODE_STRING Source, Destination;
524 NTSTATUS Status;
525 USHORT UniSize;
526
527 UniSize = min(nSize, UNICODE_STRING_MAX_CHARS - 2);
528
529 RtlInitUnicodeString(&Source, (LPWSTR)lpSrc);
530 RtlInitEmptyUnicodeString(&Destination, lpDst, UniSize * sizeof(WCHAR));
531
532 Status = RtlExpandEnvironmentStrings_U(NULL,
533 &Source,
534 &Destination,
535 &nSize);
536 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL))
537 {
538 return nSize / sizeof(WCHAR);
539 }
540
541 BaseSetLastNTError(Status);
542 return 0;
543 }
544
545 /*
546 * @implemented
547 */
548 BOOL
549 WINAPI
550 SetEnvironmentStringsA(IN LPCH NewEnvironment)
551 {
552 STUB;
553 return FALSE;
554 }
555
556 /*
557 * @implemented
558 */
559 BOOL
560 WINAPI
561 SetEnvironmentStringsW(IN LPWCH NewEnvironment)
562 {
563 STUB;
564 return FALSE;
565 }
566
567 /* EOF */