1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * FILE: dll/win32/userenv/environment.c
23 * PURPOSE: User environment functions
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include "precomp.h"
28
29 #define NDEBUG
30 #include <debug.h>
31
32 static
33 BOOL
SetUserEnvironmentVariable(PWSTR * Environment,LPWSTR lpName,LPWSTR lpValue,BOOL bExpand)34 SetUserEnvironmentVariable(PWSTR* Environment,
35 LPWSTR lpName,
36 LPWSTR lpValue,
37 BOOL bExpand)
38 {
39 NTSTATUS Status;
40 UNICODE_STRING Name;
41 UNICODE_STRING SrcValue, DstValue;
42 ULONG Length;
43 PVOID Buffer = NULL;
44 WCHAR ShortName[MAX_PATH];
45
46 if (bExpand)
47 {
48 RtlInitUnicodeString(&SrcValue, lpValue);
49
50 Length = 2 * MAX_PATH * sizeof(WCHAR);
51
52 DstValue.Length = 0;
53 DstValue.MaximumLength = Length;
54 DstValue.Buffer = Buffer = LocalAlloc(LPTR, Length);
55 if (DstValue.Buffer == NULL)
56 {
57 DPRINT1("LocalAlloc() failed\n");
58 return FALSE;
59 }
60
61 Status = RtlExpandEnvironmentStrings_U(*Environment,
62 &SrcValue,
63 &DstValue,
64 &Length);
65 if (!NT_SUCCESS(Status))
66 {
67 DPRINT1("RtlExpandEnvironmentStrings_U() failed (Status %lx)\n", Status);
68 DPRINT1("Length %lu\n", Length);
69
70 if (Buffer)
71 LocalFree(Buffer);
72
73 return FALSE;
74 }
75 }
76 else
77 {
78 RtlInitUnicodeString(&DstValue, lpValue);
79 }
80
81 if (!_wcsicmp(lpName, L"TEMP") || !_wcsicmp(lpName, L"TMP"))
82 {
83 if (GetShortPathNameW(DstValue.Buffer, ShortName, ARRAYSIZE(ShortName)))
84 {
85 RtlInitUnicodeString(&DstValue, ShortName);
86 }
87 else
88 {
89 DPRINT("GetShortPathNameW() failed for %S (Error %lu)\n", DstValue.Buffer, GetLastError());
90 }
91 }
92
93 RtlInitUnicodeString(&Name, lpName);
94
95 DPRINT("Value: %wZ\n", &DstValue);
96
97 Status = RtlSetEnvironmentVariable(Environment,
98 &Name,
99 &DstValue);
100
101 if (Buffer)
102 LocalFree(Buffer);
103
104 if (!NT_SUCCESS(Status))
105 {
106 DPRINT1("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status);
107 return FALSE;
108 }
109
110 return TRUE;
111 }
112
113
114 static
115 BOOL
AppendUserEnvironmentVariable(PWSTR * Environment,LPWSTR lpName,LPWSTR lpValue)116 AppendUserEnvironmentVariable(PWSTR* Environment,
117 LPWSTR lpName,
118 LPWSTR lpValue)
119 {
120 NTSTATUS Status;
121 UNICODE_STRING Name, Value;
122
123 RtlInitUnicodeString(&Name, lpName);
124
125 Value.Length = 0;
126 Value.MaximumLength = 1024 * sizeof(WCHAR);
127 Value.Buffer = LocalAlloc(LPTR, Value.MaximumLength);
128 if (Value.Buffer == NULL)
129 return FALSE;
130
131 Value.Buffer[0] = UNICODE_NULL;
132
133 Status = RtlQueryEnvironmentVariable_U(*Environment,
134 &Name,
135 &Value);
136 if (NT_SUCCESS(Status))
137 RtlAppendUnicodeToString(&Value, L";");
138
139 RtlAppendUnicodeToString(&Value, lpValue);
140
141 Status = RtlSetEnvironmentVariable(Environment,
142 &Name,
143 &Value);
144 LocalFree(Value.Buffer);
145 if (!NT_SUCCESS(Status))
146 {
147 DPRINT1("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status);
148 return FALSE;
149 }
150
151 return TRUE;
152 }
153
154
155 static
156 HKEY
GetCurrentUserKey(HANDLE hToken)157 GetCurrentUserKey(HANDLE hToken)
158 {
159 LONG Error;
160 UNICODE_STRING SidString;
161 HKEY hKey;
162
163 if (!GetUserSidStringFromToken(hToken, &SidString))
164 {
165 DPRINT1("GetUserSidFromToken() failed\n");
166 return NULL;
167 }
168
169 Error = RegOpenKeyExW(HKEY_USERS,
170 SidString.Buffer,
171 0,
172 MAXIMUM_ALLOWED,
173 &hKey);
174 if (Error != ERROR_SUCCESS)
175 {
176 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
177 RtlFreeUnicodeString(&SidString);
178 SetLastError((DWORD)Error);
179 return NULL;
180 }
181
182 RtlFreeUnicodeString(&SidString);
183
184 return hKey;
185 }
186
187
188 static
189 BOOL
GetUserAndDomainName(IN HANDLE hToken,OUT LPWSTR * UserName,OUT LPWSTR * DomainName)190 GetUserAndDomainName(IN HANDLE hToken,
191 OUT LPWSTR *UserName,
192 OUT LPWSTR *DomainName)
193 {
194 BOOL bRet = TRUE;
195 PSID Sid = NULL;
196 LPWSTR lpUserName = NULL;
197 LPWSTR lpDomainName = NULL;
198 DWORD cbUserName = 0;
199 DWORD cbDomainName = 0;
200 SID_NAME_USE SidNameUse;
201
202 Sid = GetUserSid(hToken);
203 if (Sid == NULL)
204 {
205 DPRINT1("GetUserSid() failed\n");
206 return FALSE;
207 }
208
209 if (!LookupAccountSidW(NULL,
210 Sid,
211 NULL,
212 &cbUserName,
213 NULL,
214 &cbDomainName,
215 &SidNameUse))
216 {
217 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
218 {
219 bRet = FALSE;
220 goto done;
221 }
222 }
223
224 lpUserName = LocalAlloc(LPTR, cbUserName * sizeof(WCHAR));
225 if (lpUserName == NULL)
226 {
227 bRet = FALSE;
228 goto done;
229 }
230
231 lpDomainName = LocalAlloc(LPTR, cbDomainName * sizeof(WCHAR));
232 if (lpDomainName == NULL)
233 {
234 bRet = FALSE;
235 goto done;
236 }
237
238 if (!LookupAccountSidW(NULL,
239 Sid,
240 lpUserName,
241 &cbUserName,
242 lpDomainName,
243 &cbDomainName,
244 &SidNameUse))
245 {
246 bRet = FALSE;
247 goto done;
248 }
249
250 *UserName = lpUserName;
251 *DomainName = lpDomainName;
252
253 done:
254 if (bRet == FALSE)
255 {
256 if (lpUserName != NULL)
257 LocalFree(lpUserName);
258
259 if (lpDomainName != NULL)
260 LocalFree(lpDomainName);
261 }
262
263 LocalFree(Sid);
264
265 return bRet;
266 }
267
268
269 static
270 BOOL
SetUserEnvironment(PWSTR * Environment,HKEY hKey,LPWSTR lpSubKeyName)271 SetUserEnvironment(PWSTR* Environment,
272 HKEY hKey,
273 LPWSTR lpSubKeyName)
274 {
275 LONG Error;
276 HKEY hEnvKey;
277 DWORD dwValues;
278 DWORD dwMaxValueNameLength;
279 DWORD dwMaxValueDataLength;
280 DWORD dwValueNameLength;
281 DWORD dwValueDataLength;
282 DWORD dwType;
283 DWORD i;
284 LPWSTR lpValueName;
285 LPWSTR lpValueData;
286
287 Error = RegOpenKeyExW(hKey,
288 lpSubKeyName,
289 0,
290 KEY_QUERY_VALUE,
291 &hEnvKey);
292 if (Error != ERROR_SUCCESS)
293 {
294 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
295 SetLastError((DWORD)Error);
296 return FALSE;
297 }
298
299 Error = RegQueryInfoKey(hEnvKey,
300 NULL,
301 NULL,
302 NULL,
303 NULL,
304 NULL,
305 NULL,
306 &dwValues,
307 &dwMaxValueNameLength,
308 &dwMaxValueDataLength,
309 NULL,
310 NULL);
311 if (Error != ERROR_SUCCESS)
312 {
313 DPRINT1("RegQueryInforKey() failed (Error %ld)\n", Error);
314 RegCloseKey(hEnvKey);
315 SetLastError((DWORD)Error);
316 return FALSE;
317 }
318
319 if (dwValues == 0)
320 {
321 RegCloseKey(hEnvKey);
322 return TRUE;
323 }
324
325 /* Allocate buffers */
326 dwMaxValueNameLength++;
327 lpValueName = LocalAlloc(LPTR, dwMaxValueNameLength * sizeof(WCHAR));
328 if (lpValueName == NULL)
329 {
330 RegCloseKey(hEnvKey);
331 return FALSE;
332 }
333
334 lpValueData = LocalAlloc(LPTR, dwMaxValueDataLength);
335 if (lpValueData == NULL)
336 {
337 LocalFree(lpValueName);
338 RegCloseKey(hEnvKey);
339 return FALSE;
340 }
341
342 /* Enumerate values */
343 for (i = 0; i < dwValues; i++)
344 {
345 dwValueNameLength = dwMaxValueNameLength;
346 dwValueDataLength = dwMaxValueDataLength;
347
348 Error = RegEnumValueW(hEnvKey,
349 i,
350 lpValueName,
351 &dwValueNameLength,
352 NULL,
353 &dwType,
354 (LPBYTE)lpValueData,
355 &dwValueDataLength);
356 if (Error == ERROR_SUCCESS)
357 {
358 if (!_wcsicmp(lpValueName, L"PATH"))
359 {
360 /* Append 'Path' environment variable */
361 AppendUserEnvironmentVariable(Environment,
362 lpValueName,
363 lpValueData);
364 }
365 else
366 {
367 /* Set environment variable */
368 SetUserEnvironmentVariable(Environment,
369 lpValueName,
370 lpValueData,
371 (dwType == REG_EXPAND_SZ));
372 }
373 }
374 else
375 {
376 LocalFree(lpValueData);
377 LocalFree(lpValueName);
378 RegCloseKey(hEnvKey);
379
380 return FALSE;
381 }
382 }
383
384 LocalFree(lpValueData);
385 LocalFree(lpValueName);
386 RegCloseKey(hEnvKey);
387
388 return TRUE;
389 }
390
391
392 static
393 BOOL
SetSystemEnvironment(PWSTR * Environment)394 SetSystemEnvironment(PWSTR* Environment)
395 {
396 LONG Error;
397 HKEY hEnvKey;
398 DWORD dwValues;
399 DWORD dwMaxValueNameLength;
400 DWORD dwMaxValueDataLength;
401 DWORD dwValueNameLength;
402 DWORD dwValueDataLength;
403 DWORD dwType;
404 DWORD i;
405 LPWSTR lpValueName;
406 LPWSTR lpValueData;
407
408 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
409 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
410 0,
411 KEY_QUERY_VALUE,
412 &hEnvKey);
413 if (Error != ERROR_SUCCESS)
414 {
415 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
416 return FALSE;
417 }
418
419 Error = RegQueryInfoKey(hEnvKey,
420 NULL,
421 NULL,
422 NULL,
423 NULL,
424 NULL,
425 NULL,
426 &dwValues,
427 &dwMaxValueNameLength,
428 &dwMaxValueDataLength,
429 NULL,
430 NULL);
431 if (Error != ERROR_SUCCESS)
432 {
433 DPRINT1("RegQueryInforKey() failed (Error %ld)\n", Error);
434 RegCloseKey(hEnvKey);
435 return FALSE;
436 }
437
438 if (dwValues == 0)
439 {
440 RegCloseKey(hEnvKey);
441 return TRUE;
442 }
443
444 /* Allocate buffers */
445 dwMaxValueNameLength++;
446 lpValueName = LocalAlloc(LPTR, dwMaxValueNameLength * sizeof(WCHAR));
447 if (lpValueName == NULL)
448 {
449 RegCloseKey(hEnvKey);
450 return FALSE;
451 }
452
453 lpValueData = LocalAlloc(LPTR, dwMaxValueDataLength);
454 if (lpValueData == NULL)
455 {
456 LocalFree(lpValueName);
457 RegCloseKey(hEnvKey);
458 return FALSE;
459 }
460
461 /* Enumerate values */
462 for (i = 0; i < dwValues; i++)
463 {
464 dwValueNameLength = dwMaxValueNameLength;
465 dwValueDataLength = dwMaxValueDataLength;
466
467 Error = RegEnumValueW(hEnvKey,
468 i,
469 lpValueName,
470 &dwValueNameLength,
471 NULL,
472 &dwType,
473 (LPBYTE)lpValueData,
474 &dwValueDataLength);
475 if (Error == ERROR_SUCCESS)
476 {
477 /* Set environment variable */
478 SetUserEnvironmentVariable(Environment,
479 lpValueName,
480 lpValueData,
481 (dwType == REG_EXPAND_SZ));
482 }
483 else
484 {
485 LocalFree(lpValueData);
486 LocalFree(lpValueName);
487 RegCloseKey(hEnvKey);
488
489 return FALSE;
490 }
491 }
492
493 LocalFree(lpValueData);
494 LocalFree(lpValueName);
495 RegCloseKey(hEnvKey);
496
497 return TRUE;
498 }
499
500
501 BOOL
502 WINAPI
CreateEnvironmentBlock(OUT LPVOID * lpEnvironment,IN HANDLE hToken,IN BOOL bInherit)503 CreateEnvironmentBlock(OUT LPVOID *lpEnvironment,
504 IN HANDLE hToken,
505 IN BOOL bInherit)
506 {
507 NTSTATUS Status;
508 LONG lError;
509 PWSTR* Environment = (PWSTR*)lpEnvironment;
510 DWORD Length;
511 DWORD dwType;
512 HKEY hKey;
513 HKEY hKeyUser;
514 LPWSTR lpUserName = NULL;
515 LPWSTR lpDomainName = NULL;
516 WCHAR Buffer[MAX_PATH];
517 WCHAR szValue[1024];
518
519 DPRINT("CreateEnvironmentBlock() called\n");
520
521 if (lpEnvironment == NULL)
522 {
523 SetLastError(ERROR_INVALID_PARAMETER);
524 return FALSE;
525 }
526
527 Status = RtlCreateEnvironment((BOOLEAN)bInherit, Environment);
528 if (!NT_SUCCESS(Status))
529 {
530 DPRINT1("RtlCreateEnvironment() failed (Status %lx)\n", Status);
531 SetLastError(RtlNtStatusToDosError(Status));
532 return FALSE;
533 }
534
535 /* Set 'SystemRoot' variable */
536 Length = ARRAYSIZE(Buffer);
537 if (GetEnvironmentVariableW(L"SystemRoot", Buffer, Length))
538 {
539 SetUserEnvironmentVariable(Environment,
540 L"SystemRoot",
541 Buffer,
542 FALSE);
543 }
544
545 /* Set 'SystemDrive' variable */
546 if (GetEnvironmentVariableW(L"SystemDrive", Buffer, Length))
547 {
548 SetUserEnvironmentVariable(Environment,
549 L"SystemDrive",
550 Buffer,
551 FALSE);
552 }
553
554 /* Set variables from Session Manager */
555 if (!SetSystemEnvironment(Environment))
556 {
557 RtlDestroyEnvironment(*Environment);
558 return FALSE;
559 }
560
561 /* Set 'COMPUTERNAME' variable */
562 Length = ARRAYSIZE(Buffer);
563 if (GetComputerNameW(Buffer, &Length))
564 {
565 SetUserEnvironmentVariable(Environment,
566 L"COMPUTERNAME",
567 Buffer,
568 FALSE);
569 }
570
571 /* Set 'ALLUSERSPROFILE' variable */
572 Length = ARRAYSIZE(Buffer);
573 if (GetAllUsersProfileDirectoryW(Buffer, &Length))
574 {
575 SetUserEnvironmentVariable(Environment,
576 L"ALLUSERSPROFILE",
577 Buffer,
578 FALSE);
579 }
580
581 /* Set 'USERPROFILE' variable to the default users profile */
582 Length = ARRAYSIZE(Buffer);
583 if (GetDefaultUserProfileDirectoryW(Buffer, &Length))
584 {
585 SetUserEnvironmentVariable(Environment,
586 L"USERPROFILE",
587 Buffer,
588 TRUE);
589 }
590
591 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
592 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
593 0,
594 KEY_READ,
595 &hKey);
596 if (lError == ERROR_SUCCESS)
597 {
598 Length = sizeof(szValue);
599 lError = RegQueryValueExW(hKey,
600 L"ProgramFilesDir",
601 NULL,
602 &dwType,
603 (LPBYTE)szValue,
604 &Length);
605 if (lError == ERROR_SUCCESS)
606 {
607 SetUserEnvironmentVariable(Environment,
608 L"ProgramFiles",
609 szValue,
610 FALSE);
611 }
612
613 Length = sizeof(szValue);
614 lError = RegQueryValueExW(hKey,
615 L"CommonFilesDir",
616 NULL,
617 &dwType,
618 (LPBYTE)szValue,
619 &Length);
620 if (lError == ERROR_SUCCESS)
621 {
622 SetUserEnvironmentVariable(Environment,
623 L"CommonProgramFiles",
624 szValue,
625 FALSE);
626 }
627
628 RegCloseKey(hKey);
629 }
630
631 /*
632 * If no user token is specified, the system environment variables are set
633 * and we stop here, otherwise continue setting the user-specific variables.
634 */
635 if (hToken == NULL)
636 return TRUE;
637
638 hKeyUser = GetCurrentUserKey(hToken);
639 if (hKeyUser == NULL)
640 {
641 DPRINT1("GetCurrentUserKey() failed\n");
642 RtlDestroyEnvironment(*Environment);
643 return FALSE;
644 }
645
646 /* Set 'USERPROFILE' variable */
647 Length = ARRAYSIZE(Buffer);
648 if (GetUserProfileDirectoryW(hToken, Buffer, &Length))
649 {
650 DWORD MinLen = 2;
651
652 SetUserEnvironmentVariable(Environment,
653 L"USERPROFILE",
654 Buffer,
655 FALSE);
656
657 // FIXME: Strangely enough the following two environment variables
658 // are not set by userenv.dll in Windows... See r68284 / CORE-9875
659 // FIXME2: This is done by msgina.dll !!
660
661 /* At least <drive letter>:<path> */
662 if (Length > MinLen)
663 {
664 /* Set 'HOMEDRIVE' variable */
665 StringCchCopyNW(szValue, ARRAYSIZE(Buffer), Buffer, MinLen);
666 SetUserEnvironmentVariable(Environment,
667 L"HOMEDRIVE",
668 szValue,
669 FALSE);
670
671 /* Set 'HOMEPATH' variable */
672 StringCchCopyNW(szValue, ARRAYSIZE(Buffer), Buffer + MinLen, Length - MinLen);
673 SetUserEnvironmentVariable(Environment,
674 L"HOMEPATH",
675 szValue,
676 FALSE);
677 }
678 }
679 else
680 {
681 DPRINT1("GetUserProfileDirectoryW failed with error %lu\n", GetLastError());
682 }
683
684 if (GetUserAndDomainName(hToken,
685 &lpUserName,
686 &lpDomainName))
687 {
688 /* Set 'USERNAME' variable */
689 SetUserEnvironmentVariable(Environment,
690 L"USERNAME",
691 lpUserName,
692 FALSE);
693
694 /* Set 'USERDOMAIN' variable */
695 SetUserEnvironmentVariable(Environment,
696 L"USERDOMAIN",
697 lpDomainName,
698 FALSE);
699
700 if (lpUserName != NULL)
701 LocalFree(lpUserName);
702
703 if (lpDomainName != NULL)
704 LocalFree(lpDomainName);
705 }
706
707 /* Set user environment variables */
708 SetUserEnvironment(Environment,
709 hKeyUser,
710 L"Environment");
711
712 /* Set user volatile environment variables */
713 SetUserEnvironment(Environment,
714 hKeyUser,
715 L"Volatile Environment");
716
717 RegCloseKey(hKeyUser);
718
719 return TRUE;
720 }
721
722
723 BOOL
724 WINAPI
DestroyEnvironmentBlock(IN LPVOID lpEnvironment)725 DestroyEnvironmentBlock(IN LPVOID lpEnvironment)
726 {
727 DPRINT("DestroyEnvironmentBlock() called\n");
728
729 if (lpEnvironment == NULL)
730 {
731 SetLastError(ERROR_INVALID_PARAMETER);
732 return FALSE;
733 }
734
735 RtlDestroyEnvironment(lpEnvironment);
736
737 return TRUE;
738 }
739
740
741 BOOL
742 WINAPI
ExpandEnvironmentStringsForUserW(IN HANDLE hToken,IN LPCWSTR lpSrc,OUT LPWSTR lpDest,IN DWORD dwSize)743 ExpandEnvironmentStringsForUserW(IN HANDLE hToken,
744 IN LPCWSTR lpSrc,
745 OUT LPWSTR lpDest,
746 IN DWORD dwSize)
747 {
748 BOOL Ret = FALSE;
749 PVOID lpEnvironment;
750
751 if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
752 {
753 SetLastError(ERROR_INVALID_PARAMETER);
754 return FALSE;
755 }
756
757 if (CreateEnvironmentBlock(&lpEnvironment,
758 hToken,
759 FALSE))
760 {
761 UNICODE_STRING SrcU, DestU;
762 NTSTATUS Status;
763
764 /* Initialize the strings */
765 RtlInitUnicodeString(&SrcU, lpSrc);
766 DestU.Length = 0;
767 DestU.MaximumLength = dwSize * sizeof(WCHAR);
768 DestU.Buffer = lpDest;
769
770 /* Expand the strings */
771 Status = RtlExpandEnvironmentStrings_U((PWSTR)lpEnvironment,
772 &SrcU,
773 &DestU,
774 NULL);
775
776 DestroyEnvironmentBlock(lpEnvironment);
777
778 if (NT_SUCCESS(Status))
779 {
780 Ret = TRUE;
781 }
782 else
783 {
784 SetLastError(RtlNtStatusToDosError(Status));
785 }
786 }
787
788 return Ret;
789 }
790
791
792 BOOL
793 WINAPI
ExpandEnvironmentStringsForUserA(IN HANDLE hToken,IN LPCSTR lpSrc,OUT LPSTR lpDest,IN DWORD dwSize)794 ExpandEnvironmentStringsForUserA(IN HANDLE hToken,
795 IN LPCSTR lpSrc,
796 OUT LPSTR lpDest,
797 IN DWORD dwSize)
798 {
799 BOOL Ret = FALSE;
800 DWORD dwSrcLen;
801 LPWSTR lpSrcW = NULL, lpDestW = NULL;
802
803 if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
804 {
805 SetLastError(ERROR_INVALID_PARAMETER);
806 return FALSE;
807 }
808
809 dwSrcLen = strlen(lpSrc);
810 lpSrcW = (LPWSTR)GlobalAlloc(GMEM_FIXED,
811 (dwSrcLen + 1) * sizeof(WCHAR));
812 if (lpSrcW == NULL ||
813 MultiByteToWideChar(CP_ACP,
814 0,
815 lpSrc,
816 -1,
817 lpSrcW,
818 dwSrcLen + 1) == 0)
819 {
820 goto Cleanup;
821 }
822
823 lpDestW = (LPWSTR)GlobalAlloc(GMEM_FIXED,
824 dwSize * sizeof(WCHAR));
825 if (lpDestW == NULL)
826 goto Cleanup;
827
828 Ret = ExpandEnvironmentStringsForUserW(hToken,
829 lpSrcW,
830 lpDestW,
831 dwSize);
832 if (Ret)
833 {
834 if (WideCharToMultiByte(CP_ACP,
835 0,
836 lpDestW,
837 -1,
838 lpDest,
839 dwSize,
840 NULL,
841 NULL) == 0)
842 {
843 Ret = FALSE;
844 }
845 }
846
847 Cleanup:
848 if (lpSrcW != NULL)
849 GlobalFree((HGLOBAL)lpSrcW);
850
851 if (lpDestW != NULL)
852 GlobalFree((HGLOBAL)lpDestW);
853
854 return Ret;
855 }
856
857 /* EOF */
858