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