Create the AHCI branch for Aman's work
[reactos.git] / dll / win32 / userenv / profile.c
1 /*
2 * ReactOS kernel
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 /*
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS system libraries
21 * FILE: dll/win32/userenv/profile.c
22 * PURPOSE: User profile code
23 * PROGRAMMERS: Eric Kohl
24 * Hervé Poussineau
25 */
26
27 #include "precomp.h"
28
29 #include <sddl.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /* FUNCTIONS ***************************************************************/
35
36 BOOL
37 AppendSystemPostfix(LPWSTR lpName,
38 DWORD dwMaxLength)
39 {
40 WCHAR szSystemRoot[MAX_PATH];
41 LPWSTR lpszPostfix;
42 LPWSTR lpszPtr;
43
44 /* Build profile name postfix */
45 if (!ExpandEnvironmentStringsW(L"%SystemRoot%",
46 szSystemRoot,
47 MAX_PATH))
48 {
49 DPRINT1("Error: %lu\n", GetLastError());
50 return FALSE;
51 }
52
53 _wcsupr(szSystemRoot);
54
55 /* Get name postfix */
56 szSystemRoot[2] = L'.';
57 lpszPostfix = &szSystemRoot[2];
58 lpszPtr = lpszPostfix;
59 while (*lpszPtr != (WCHAR)0)
60 {
61 if (*lpszPtr == L'\\')
62 *lpszPtr = '_';
63 lpszPtr++;
64 }
65
66 if (wcslen(lpName) + wcslen(lpszPostfix) + 1 >= dwMaxLength)
67 {
68 DPRINT1("Error: buffer overflow\n");
69 SetLastError(ERROR_BUFFER_OVERFLOW);
70 return FALSE;
71 }
72
73 wcscat(lpName, lpszPostfix);
74
75 return TRUE;
76 }
77
78
79 static
80 BOOL
81 AcquireRemoveRestorePrivilege(IN BOOL bAcquire)
82 {
83 BOOL bRet = FALSE;
84 HANDLE Token;
85 TOKEN_PRIVILEGES TokenPriv;
86
87 DPRINT("AcquireRemoveRestorePrivilege(%d)\n", bAcquire);
88
89 if (OpenProcessToken(GetCurrentProcess(),
90 TOKEN_ADJUST_PRIVILEGES,
91 &Token))
92 {
93 TokenPriv.PrivilegeCount = 1;
94 TokenPriv.Privileges[0].Attributes = (bAcquire ? SE_PRIVILEGE_ENABLED : 0);
95
96 if (LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &TokenPriv.Privileges[0].Luid))
97 {
98 bRet = AdjustTokenPrivileges(Token, FALSE, &TokenPriv, 0, NULL, NULL);
99
100 if (!bRet)
101 {
102 DPRINT1("AdjustTokenPrivileges() failed with error %lu\n", GetLastError());
103 }
104 else if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
105 {
106 DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
107 bRet = FALSE;
108 }
109 }
110 else
111 {
112 DPRINT1("LookupPrivilegeValue() failed with error %lu\n", GetLastError());
113 }
114
115 CloseHandle(Token);
116 }
117 else
118 {
119 DPRINT1("OpenProcessToken() failed with error %lu\n", GetLastError());
120 }
121
122 return bRet;
123 }
124
125
126 BOOL
127 WINAPI
128 CreateUserProfileA(PSID Sid,
129 LPCSTR lpUserName)
130 {
131 UNICODE_STRING UserName;
132 BOOL bResult;
133
134 if (!RtlCreateUnicodeStringFromAsciiz(&UserName,
135 (LPSTR)lpUserName))
136 {
137 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
138 return FALSE;
139 }
140
141 bResult = CreateUserProfileW(Sid, UserName.Buffer);
142
143 RtlFreeUnicodeString(&UserName);
144
145 return bResult;
146 }
147
148
149 BOOL
150 WINAPI
151 CreateUserProfileW(PSID Sid,
152 LPCWSTR lpUserName)
153 {
154 WCHAR szRawProfilesPath[MAX_PATH];
155 WCHAR szProfilesPath[MAX_PATH];
156 WCHAR szUserProfilePath[MAX_PATH];
157 WCHAR szDefaultUserPath[MAX_PATH];
158 WCHAR szUserProfileName[MAX_PATH];
159 WCHAR szBuffer[MAX_PATH];
160 LPWSTR SidString;
161 DWORD dwLength;
162 DWORD dwDisposition;
163 UINT i;
164 HKEY hKey;
165 BOOL bRet = TRUE;
166 LONG Error;
167
168 DPRINT("CreateUserProfileW() called\n");
169
170 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
171 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
172 0,
173 KEY_QUERY_VALUE,
174 &hKey);
175 if (Error != ERROR_SUCCESS)
176 {
177 DPRINT1("Error: %lu\n", Error);
178 SetLastError((DWORD)Error);
179 return FALSE;
180 }
181
182 /* Get profiles path */
183 dwLength = MAX_PATH * sizeof(WCHAR);
184 Error = RegQueryValueExW(hKey,
185 L"ProfilesDirectory",
186 NULL,
187 NULL,
188 (LPBYTE)szRawProfilesPath,
189 &dwLength);
190 if (Error != ERROR_SUCCESS)
191 {
192 DPRINT1("Error: %lu\n", Error);
193 RegCloseKey(hKey);
194 SetLastError((DWORD)Error);
195 return FALSE;
196 }
197
198 /* Expand it */
199 if (!ExpandEnvironmentStringsW(szRawProfilesPath,
200 szProfilesPath,
201 MAX_PATH))
202 {
203 DPRINT1("Error: %lu\n", GetLastError());
204 RegCloseKey(hKey);
205 return FALSE;
206 }
207
208 /* create the profiles directory if it does not yet exist */
209 if (!CreateDirectoryW(szProfilesPath, NULL))
210 {
211 if (GetLastError() != ERROR_ALREADY_EXISTS)
212 {
213 DPRINT1("Error: %lu\n", GetLastError());
214 return FALSE;
215 }
216 }
217
218 /* Get default user path */
219 dwLength = MAX_PATH * sizeof(WCHAR);
220 Error = RegQueryValueExW(hKey,
221 L"DefaultUserProfile",
222 NULL,
223 NULL,
224 (LPBYTE)szBuffer,
225 &dwLength);
226 if (Error != ERROR_SUCCESS)
227 {
228 DPRINT1("Error: %lu\n", Error);
229 RegCloseKey(hKey);
230 SetLastError((DWORD)Error);
231 return FALSE;
232 }
233
234 RegCloseKey (hKey);
235
236 wcscpy(szUserProfileName, lpUserName);
237
238 wcscpy(szUserProfilePath, szProfilesPath);
239 wcscat(szUserProfilePath, L"\\");
240 wcscat(szUserProfilePath, szUserProfileName);
241
242 wcscpy(szDefaultUserPath, szProfilesPath);
243 wcscat(szDefaultUserPath, L"\\");
244 wcscat(szDefaultUserPath, szBuffer);
245
246 /* Create user profile directory */
247 if (!CreateDirectoryW(szUserProfilePath, NULL))
248 {
249 if (GetLastError() != ERROR_ALREADY_EXISTS)
250 {
251 DPRINT1("Error: %lu\n", GetLastError());
252 return FALSE;
253 }
254
255 for (i = 0; i < 1000; i++)
256 {
257 swprintf(szUserProfileName, L"%s.%03u", lpUserName, i);
258
259 wcscpy(szUserProfilePath, szProfilesPath);
260 wcscat(szUserProfilePath, L"\\");
261 wcscat(szUserProfilePath, szUserProfileName);
262
263 if (CreateDirectoryW(szUserProfilePath, NULL))
264 break;
265
266 if (GetLastError() != ERROR_ALREADY_EXISTS)
267 {
268 DPRINT1("Error: %lu\n", GetLastError());
269 return FALSE;
270 }
271 }
272 }
273
274 /* Copy default user directory */
275 if (!CopyDirectory(szUserProfilePath, szDefaultUserPath))
276 {
277 DPRINT1("Error: %lu\n", GetLastError());
278 return FALSE;
279 }
280
281 /* Add profile to profile list */
282 if (!ConvertSidToStringSidW(Sid,
283 &SidString))
284 {
285 DPRINT1("Error: %lu\n", GetLastError());
286 return FALSE;
287 }
288
289 wcscpy(szBuffer,
290 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
291 wcscat(szBuffer, SidString);
292
293 /* Create user profile key */
294 Error = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
295 szBuffer,
296 0,
297 NULL,
298 REG_OPTION_NON_VOLATILE,
299 KEY_ALL_ACCESS,
300 NULL,
301 &hKey,
302 &dwDisposition);
303 if (Error != ERROR_SUCCESS)
304 {
305 DPRINT1("Error: %lu\n", Error);
306 bRet = FALSE;
307 goto Done;
308 }
309
310 /* Create non-expanded user profile path */
311 wcscpy(szBuffer, szRawProfilesPath);
312 wcscat(szBuffer, L"\\");
313 wcscat(szBuffer, szUserProfileName);
314
315 /* Set 'ProfileImagePath' value (non-expanded) */
316 Error = RegSetValueExW(hKey,
317 L"ProfileImagePath",
318 0,
319 REG_EXPAND_SZ,
320 (LPBYTE)szBuffer,
321 (wcslen (szBuffer) + 1) * sizeof(WCHAR));
322 if (Error != ERROR_SUCCESS)
323 {
324 DPRINT1("Error: %lu\n", Error);
325 RegCloseKey(hKey);
326 bRet = FALSE;
327 goto Done;
328 }
329
330 /* Set 'Sid' value */
331 Error = RegSetValueExW(hKey,
332 L"Sid",
333 0,
334 REG_BINARY,
335 Sid,
336 GetLengthSid(Sid));
337 if (Error != ERROR_SUCCESS)
338 {
339 DPRINT1("Error: %lu\n", Error);
340 RegCloseKey(hKey);
341 bRet = FALSE;
342 goto Done;
343 }
344
345 RegCloseKey(hKey);
346
347 /* Create user hive name */
348 wcscpy(szBuffer, szUserProfilePath);
349 wcscat(szBuffer, L"\\ntuser.dat");
350
351 /* Acquire restore privilege */
352 if (!AcquireRemoveRestorePrivilege(TRUE))
353 {
354 Error = GetLastError();
355 DPRINT1("Error: %lu\n", Error);
356 bRet = FALSE;
357 goto Done;
358 }
359
360 /* Create new user hive */
361 Error = RegLoadKeyW(HKEY_USERS,
362 SidString,
363 szBuffer);
364 AcquireRemoveRestorePrivilege(FALSE);
365 if (Error != ERROR_SUCCESS)
366 {
367 DPRINT1("Error: %lu\n", Error);
368 bRet = FALSE;
369 goto Done;
370 }
371
372 /* Initialize user hive */
373 if (!CreateUserHive(SidString, szUserProfilePath))
374 {
375 Error = GetLastError();
376 DPRINT1("Error: %lu\n", Error);
377 bRet = FALSE;
378 }
379
380 /* Unload the hive */
381 AcquireRemoveRestorePrivilege(TRUE);
382 RegUnLoadKeyW(HKEY_USERS, SidString);
383 AcquireRemoveRestorePrivilege(FALSE);
384
385 Done:
386 LocalFree((HLOCAL)SidString);
387 SetLastError((DWORD)Error);
388
389 DPRINT("CreateUserProfileW() done\n");
390
391 return bRet;
392 }
393
394
395 BOOL
396 WINAPI
397 CreateUserProfileExA(IN PSID pSid,
398 IN LPCSTR lpUserName,
399 IN LPCSTR lpUserHive OPTIONAL,
400 OUT LPSTR lpProfileDir OPTIONAL,
401 IN DWORD dwDirSize,
402 IN BOOL bWin9xUpg)
403 {
404 DPRINT1("CreateUserProfileExA() not implemented!\n");
405 return FALSE;
406 }
407
408
409 BOOL
410 WINAPI
411 CreateUserProfileExW(IN PSID pSid,
412 IN LPCWSTR lpUserName,
413 IN LPCWSTR lpUserHive OPTIONAL,
414 OUT LPWSTR lpProfileDir OPTIONAL,
415 IN DWORD dwDirSize,
416 IN BOOL bWin9xUpg)
417 {
418 DPRINT1("CreateUserProfileExW() not implemented!\n");
419 return FALSE;
420 }
421
422
423 BOOL
424 WINAPI
425 GetAllUsersProfileDirectoryA(LPSTR lpProfileDir,
426 LPDWORD lpcchSize)
427 {
428 LPWSTR lpBuffer;
429 BOOL bResult;
430
431 lpBuffer = GlobalAlloc(GMEM_FIXED,
432 *lpcchSize * sizeof(WCHAR));
433 if (lpBuffer == NULL)
434 return FALSE;
435
436 bResult = GetAllUsersProfileDirectoryW(lpBuffer,
437 lpcchSize);
438 if (bResult)
439 {
440 WideCharToMultiByte(CP_ACP,
441 0,
442 lpBuffer,
443 -1,
444 lpProfileDir,
445 *lpcchSize,
446 NULL,
447 NULL);
448 }
449
450 GlobalFree(lpBuffer);
451
452 return bResult;
453 }
454
455
456 BOOL
457 WINAPI
458 GetAllUsersProfileDirectoryW(LPWSTR lpProfileDir,
459 LPDWORD lpcchSize)
460 {
461 WCHAR szProfilePath[MAX_PATH];
462 WCHAR szBuffer[MAX_PATH];
463 DWORD dwLength;
464 HKEY hKey;
465 LONG Error;
466
467 if (!lpcchSize)
468 {
469 SetLastError(ERROR_INVALID_PARAMETER);
470 return FALSE;
471 }
472
473 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
474 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
475 0,
476 KEY_QUERY_VALUE,
477 &hKey);
478 if (Error != ERROR_SUCCESS)
479 {
480 DPRINT1("Error: %lu\n", Error);
481 SetLastError((DWORD)Error);
482 return FALSE;
483 }
484
485 /* Get profiles path */
486 dwLength = sizeof(szBuffer);
487 Error = RegQueryValueExW(hKey,
488 L"ProfilesDirectory",
489 NULL,
490 NULL,
491 (LPBYTE)szBuffer,
492 &dwLength);
493 if (Error != ERROR_SUCCESS)
494 {
495 DPRINT1("Error: %lu\n", Error);
496 RegCloseKey(hKey);
497 SetLastError((DWORD)Error);
498 return FALSE;
499 }
500
501 /* Expand it */
502 if (!ExpandEnvironmentStringsW(szBuffer,
503 szProfilePath,
504 MAX_PATH))
505 {
506 DPRINT1("Error: %lu\n", GetLastError());
507 RegCloseKey (hKey);
508 return FALSE;
509 }
510
511 /* Get 'AllUsersProfile' name */
512 dwLength = sizeof(szBuffer);
513 Error = RegQueryValueExW(hKey,
514 L"AllUsersProfile",
515 NULL,
516 NULL,
517 (LPBYTE)szBuffer,
518 &dwLength);
519 if (Error != ERROR_SUCCESS)
520 {
521 DPRINT1("Error: %lu\n", Error);
522 RegCloseKey(hKey);
523 SetLastError((DWORD)Error);
524 return FALSE;
525 }
526
527 RegCloseKey (hKey);
528
529 wcscat(szProfilePath, L"\\");
530 wcscat(szProfilePath, szBuffer);
531
532 dwLength = wcslen(szProfilePath) + 1;
533 if (lpProfileDir != NULL)
534 {
535 if (*lpcchSize < dwLength)
536 {
537 *lpcchSize = dwLength;
538 SetLastError(ERROR_INSUFFICIENT_BUFFER);
539 return FALSE;
540 }
541
542 wcscpy(lpProfileDir, szProfilePath);
543 }
544
545 *lpcchSize = dwLength;
546
547 return TRUE;
548 }
549
550
551 BOOL
552 WINAPI
553 GetDefaultUserProfileDirectoryA(LPSTR lpProfileDir,
554 LPDWORD lpcchSize)
555 {
556 LPWSTR lpBuffer;
557 BOOL bResult;
558
559 lpBuffer = GlobalAlloc(GMEM_FIXED,
560 *lpcchSize * sizeof(WCHAR));
561 if (lpBuffer == NULL)
562 return FALSE;
563
564 bResult = GetDefaultUserProfileDirectoryW(lpBuffer,
565 lpcchSize);
566 if (bResult)
567 {
568 WideCharToMultiByte(CP_ACP,
569 0,
570 lpBuffer,
571 -1,
572 lpProfileDir,
573 *lpcchSize,
574 NULL,
575 NULL);
576 }
577
578 GlobalFree(lpBuffer);
579
580 return bResult;
581 }
582
583
584 BOOL
585 WINAPI
586 GetDefaultUserProfileDirectoryW(LPWSTR lpProfileDir,
587 LPDWORD lpcchSize)
588 {
589 WCHAR szProfilePath[MAX_PATH];
590 WCHAR szBuffer[MAX_PATH];
591 DWORD dwLength;
592 HKEY hKey;
593 LONG Error;
594
595 if (!lpcchSize)
596 {
597 SetLastError(ERROR_INVALID_PARAMETER);
598 return FALSE;
599 }
600
601 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
602 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
603 0,
604 KEY_QUERY_VALUE,
605 &hKey);
606 if (Error != ERROR_SUCCESS)
607 {
608 DPRINT1("Error: %lu\n", Error);
609 SetLastError((DWORD)Error);
610 return FALSE;
611 }
612
613 /* Get profiles path */
614 dwLength = sizeof(szBuffer);
615 Error = RegQueryValueExW(hKey,
616 L"ProfilesDirectory",
617 NULL,
618 NULL,
619 (LPBYTE)szBuffer,
620 &dwLength);
621 if (Error != ERROR_SUCCESS)
622 {
623 DPRINT1("Error: %lu\n", Error);
624 RegCloseKey(hKey);
625 SetLastError((DWORD)Error);
626 return FALSE;
627 }
628
629 /* Expand it */
630 if (!ExpandEnvironmentStringsW(szBuffer,
631 szProfilePath,
632 MAX_PATH))
633 {
634 DPRINT1("Error: %lu\n", GetLastError());
635 RegCloseKey(hKey);
636 return FALSE;
637 }
638
639 /* Get 'DefaultUserProfile' name */
640 dwLength = sizeof(szBuffer);
641 Error = RegQueryValueExW(hKey,
642 L"DefaultUserProfile",
643 NULL,
644 NULL,
645 (LPBYTE)szBuffer,
646 &dwLength);
647 if (Error != ERROR_SUCCESS)
648 {
649 DPRINT1("Error: %lu\n", Error);
650 RegCloseKey(hKey);
651 SetLastError((DWORD)Error);
652 return FALSE;
653 }
654
655 RegCloseKey(hKey);
656
657 wcscat(szProfilePath, L"\\");
658 wcscat(szProfilePath, szBuffer);
659
660 dwLength = wcslen(szProfilePath) + 1;
661 if (lpProfileDir != NULL)
662 {
663 if (*lpcchSize < dwLength)
664 {
665 *lpcchSize = dwLength;
666 SetLastError(ERROR_INSUFFICIENT_BUFFER);
667 return FALSE;
668 }
669
670 wcscpy(lpProfileDir, szProfilePath);
671 }
672
673 *lpcchSize = dwLength;
674
675 return TRUE;
676 }
677
678
679 BOOL
680 WINAPI
681 GetProfilesDirectoryA(LPSTR lpProfileDir,
682 LPDWORD lpcchSize)
683 {
684 LPWSTR lpBuffer;
685 BOOL bResult;
686
687 if (!lpProfileDir || !lpcchSize)
688 {
689 SetLastError(ERROR_INVALID_PARAMETER);
690 return FALSE;
691 }
692
693 lpBuffer = GlobalAlloc(GMEM_FIXED,
694 *lpcchSize * sizeof(WCHAR));
695 if (lpBuffer == NULL)
696 return FALSE;
697
698 bResult = GetProfilesDirectoryW(lpBuffer,
699 lpcchSize);
700 if (bResult)
701 {
702 bResult = WideCharToMultiByte(CP_ACP,
703 0,
704 lpBuffer,
705 -1,
706 lpProfileDir,
707 *lpcchSize,
708 NULL,
709 NULL);
710 }
711
712 GlobalFree(lpBuffer);
713
714 return bResult;
715 }
716
717
718 BOOL
719 WINAPI
720 GetProfilesDirectoryW(LPWSTR lpProfilesDir,
721 LPDWORD lpcchSize)
722 {
723 WCHAR szProfilesPath[MAX_PATH];
724 WCHAR szBuffer[MAX_PATH];
725 DWORD dwLength;
726 HKEY hKey;
727 LONG Error;
728 BOOL bRet = FALSE;
729
730 if (!lpcchSize)
731 {
732 SetLastError(ERROR_INVALID_PARAMETER);
733 return FALSE;
734 }
735
736 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
737 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
738 0,
739 KEY_QUERY_VALUE,
740 &hKey);
741 if (Error != ERROR_SUCCESS)
742 {
743 DPRINT1("Error: %lu\n", Error);
744 SetLastError((DWORD)Error);
745 return FALSE;
746 }
747
748 /* Get profiles path */
749 dwLength = sizeof(szBuffer);
750 Error = RegQueryValueExW(hKey,
751 L"ProfilesDirectory",
752 NULL,
753 NULL,
754 (LPBYTE)szBuffer,
755 &dwLength);
756 if (Error != ERROR_SUCCESS)
757 {
758 DPRINT1("Error: %lu\n", Error);
759 RegCloseKey(hKey);
760 SetLastError((DWORD)Error);
761 return FALSE;
762 }
763
764 RegCloseKey(hKey);
765
766 /* Expand it */
767 if (!ExpandEnvironmentStringsW(szBuffer,
768 szProfilesPath,
769 MAX_PATH))
770 {
771 DPRINT1("Error: %lu\n", GetLastError());
772 return FALSE;
773 }
774
775 dwLength = wcslen (szProfilesPath) + 1;
776 if (lpProfilesDir != NULL)
777 {
778 if (*lpcchSize < dwLength)
779 {
780 SetLastError(ERROR_INSUFFICIENT_BUFFER);
781 }
782 else
783 {
784 wcscpy(lpProfilesDir, szProfilesPath);
785 bRet = TRUE;
786 }
787 }
788 else
789 {
790 SetLastError(ERROR_INSUFFICIENT_BUFFER);
791 }
792
793 *lpcchSize = dwLength;
794
795 return bRet;
796 }
797
798
799 BOOL
800 WINAPI
801 GetUserProfileDirectoryA(HANDLE hToken,
802 LPSTR lpProfileDir,
803 LPDWORD lpcchSize)
804 {
805 LPWSTR lpBuffer;
806 BOOL bResult;
807
808 if (!lpProfileDir || !lpcchSize)
809 {
810 SetLastError( ERROR_INVALID_PARAMETER );
811 return FALSE;
812 }
813
814 lpBuffer = GlobalAlloc(GMEM_FIXED,
815 *lpcchSize * sizeof(WCHAR));
816 if (lpBuffer == NULL)
817 return FALSE;
818
819 bResult = GetUserProfileDirectoryW(hToken,
820 lpBuffer,
821 lpcchSize);
822 if (bResult)
823 {
824 WideCharToMultiByte(CP_ACP,
825 0,
826 lpBuffer,
827 -1,
828 lpProfileDir,
829 *lpcchSize,
830 NULL,
831 NULL);
832 }
833
834 GlobalFree(lpBuffer);
835
836 return bResult;
837 }
838
839
840 BOOL
841 WINAPI
842 GetUserProfileDirectoryW(HANDLE hToken,
843 LPWSTR lpProfileDir,
844 LPDWORD lpcchSize)
845 {
846 UNICODE_STRING SidString;
847 WCHAR szKeyName[MAX_PATH];
848 WCHAR szRawImagePath[MAX_PATH];
849 WCHAR szImagePath[MAX_PATH];
850 DWORD dwLength;
851 HKEY hKey;
852 LONG Error;
853
854 if (!hToken)
855 {
856 SetLastError(ERROR_INVALID_HANDLE);
857 return FALSE;
858 }
859
860 if (!lpcchSize)
861 {
862 SetLastError(ERROR_INVALID_PARAMETER);
863 return FALSE;
864 }
865
866 if (!GetUserSidStringFromToken(hToken,
867 &SidString))
868 {
869 DPRINT1("GetUserSidFromToken() failed\n");
870 return FALSE;
871 }
872
873 DPRINT("SidString: '%wZ'\n", &SidString);
874
875 wcscpy(szKeyName,
876 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
877 wcscat(szKeyName,
878 SidString.Buffer);
879
880 RtlFreeUnicodeString(&SidString);
881
882 DPRINT("KeyName: '%S'\n", szKeyName);
883
884 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
885 szKeyName,
886 0,
887 KEY_QUERY_VALUE,
888 &hKey);
889 if (Error != ERROR_SUCCESS)
890 {
891 DPRINT1("Error: %lu\n", Error);
892 SetLastError((DWORD)Error);
893 return FALSE;
894 }
895
896 dwLength = sizeof(szRawImagePath);
897 Error = RegQueryValueExW(hKey,
898 L"ProfileImagePath",
899 NULL,
900 NULL,
901 (LPBYTE)szRawImagePath,
902 &dwLength);
903 if (Error != ERROR_SUCCESS)
904 {
905 DPRINT1("Error: %lu\n", Error);
906 RegCloseKey(hKey);
907 SetLastError((DWORD)Error);
908 return FALSE;
909 }
910
911 RegCloseKey(hKey);
912
913 DPRINT("RawImagePath: '%S'\n", szRawImagePath);
914
915 /* Expand it */
916 if (!ExpandEnvironmentStringsW(szRawImagePath,
917 szImagePath,
918 MAX_PATH))
919 {
920 DPRINT1 ("Error: %lu\n", GetLastError());
921 return FALSE;
922 }
923
924 DPRINT("ImagePath: '%S'\n", szImagePath);
925
926 dwLength = wcslen (szImagePath) + 1;
927 if (*lpcchSize < dwLength)
928 {
929 *lpcchSize = dwLength;
930 SetLastError(ERROR_INSUFFICIENT_BUFFER);
931 return FALSE;
932 }
933
934 *lpcchSize = dwLength;
935 wcscpy(lpProfileDir, szImagePath);
936
937 return TRUE;
938 }
939
940
941 static
942 BOOL
943 CheckForLoadedProfile(HANDLE hToken)
944 {
945 UNICODE_STRING SidString;
946 HKEY hKey;
947
948 DPRINT("CheckForLoadedProfile() called\n");
949
950 if (!GetUserSidStringFromToken(hToken,
951 &SidString))
952 {
953 DPRINT1("GetUserSidFromToken() failed\n");
954 return FALSE;
955 }
956
957 if (RegOpenKeyExW(HKEY_USERS,
958 SidString.Buffer,
959 0,
960 MAXIMUM_ALLOWED,
961 &hKey))
962 {
963 DPRINT("Profile not loaded\n");
964 RtlFreeUnicodeString(&SidString);
965 return FALSE;
966 }
967
968 RegCloseKey(hKey);
969
970 RtlFreeUnicodeString(&SidString);
971
972 DPRINT("Profile already loaded\n");
973
974 return TRUE;
975 }
976
977
978 BOOL
979 WINAPI
980 LoadUserProfileA(IN HANDLE hToken,
981 IN OUT LPPROFILEINFOA lpProfileInfo)
982 {
983 BOOL bResult = FALSE;
984 PROFILEINFOW ProfileInfoW = {0};
985 int len;
986
987 DPRINT("LoadUserProfileA() called\n");
988
989 /* Check profile info */
990 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOA)) ||
991 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
992 {
993 SetLastError(ERROR_INVALID_PARAMETER);
994 return FALSE;
995 }
996
997 /* Convert the structure to UNICODE... */
998 ProfileInfoW.dwSize = sizeof(PROFILEINFOW);
999 ProfileInfoW.dwFlags = lpProfileInfo->dwFlags;
1000
1001 if (lpProfileInfo->lpUserName)
1002 {
1003 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, NULL, 0);
1004 ProfileInfoW.lpUserName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1005 if (!ProfileInfoW.lpUserName)
1006 {
1007 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1008 goto cleanup;
1009 }
1010 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, ProfileInfoW.lpUserName, len);
1011 }
1012
1013 if (lpProfileInfo->lpProfilePath)
1014 {
1015 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, NULL, 0);
1016 ProfileInfoW.lpProfilePath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1017 if (!ProfileInfoW.lpProfilePath)
1018 {
1019 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1020 goto cleanup;
1021 }
1022 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, ProfileInfoW.lpProfilePath, len);
1023 }
1024
1025 if (lpProfileInfo->lpDefaultPath)
1026 {
1027 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, NULL, 0);
1028 ProfileInfoW.lpDefaultPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1029 if (!ProfileInfoW.lpDefaultPath)
1030 {
1031 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1032 goto cleanup;
1033 }
1034 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, ProfileInfoW.lpDefaultPath, len);
1035 }
1036
1037 if (lpProfileInfo->lpServerName)
1038 {
1039 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, NULL, 0);
1040 ProfileInfoW.lpServerName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1041 if (!ProfileInfoW.lpServerName)
1042 {
1043 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1044 goto cleanup;
1045 }
1046 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, ProfileInfoW.lpServerName, len);
1047 }
1048
1049 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && lpProfileInfo->lpPolicyPath)
1050 {
1051 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, NULL, 0);
1052 ProfileInfoW.lpPolicyPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1053 if (!ProfileInfoW.lpPolicyPath)
1054 {
1055 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1056 goto cleanup;
1057 }
1058 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, ProfileInfoW.lpPolicyPath, len);
1059 }
1060
1061 /* ... and call the UNICODE function */
1062 bResult = LoadUserProfileW(hToken, &ProfileInfoW);
1063
1064 /* Save the returned value */
1065 lpProfileInfo->hProfile = ProfileInfoW.hProfile;
1066
1067 cleanup:
1068 /* Memory cleanup */
1069 if (ProfileInfoW.lpUserName)
1070 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpUserName);
1071
1072 if (ProfileInfoW.lpProfilePath)
1073 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpProfilePath);
1074
1075 if (ProfileInfoW.lpDefaultPath)
1076 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpDefaultPath);
1077
1078 if (ProfileInfoW.lpServerName)
1079 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpServerName);
1080
1081 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && ProfileInfoW.lpPolicyPath)
1082 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpPolicyPath);
1083
1084 return bResult;
1085 }
1086
1087
1088 BOOL
1089 WINAPI
1090 LoadUserProfileW(IN HANDLE hToken,
1091 IN OUT LPPROFILEINFOW lpProfileInfo)
1092 {
1093 WCHAR szUserHivePath[MAX_PATH];
1094 LPWSTR UserName = NULL, Domain = NULL;
1095 DWORD UserNameLength = 0, DomainLength = 0;
1096 PTOKEN_USER UserSid = NULL;
1097 SID_NAME_USE AccountType;
1098 UNICODE_STRING SidString = { 0, 0, NULL };
1099 LONG Error;
1100 BOOL ret = FALSE;
1101 DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
1102
1103 DPRINT("LoadUserProfileW() called\n");
1104
1105 /* Check profile info */
1106 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOW)) ||
1107 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
1108 {
1109 SetLastError(ERROR_INVALID_PARAMETER);
1110 return FALSE;
1111 }
1112
1113 /* Don't load a profile twice */
1114 if (CheckForLoadedProfile(hToken))
1115 {
1116 DPRINT ("Profile already loaded\n");
1117 lpProfileInfo->hProfile = NULL;
1118 return TRUE;
1119 }
1120
1121 if (lpProfileInfo->lpProfilePath)
1122 {
1123 wcscpy(szUserHivePath, lpProfileInfo->lpProfilePath);
1124 }
1125 else
1126 {
1127 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
1128 if (!GetProfilesDirectoryW(szUserHivePath, &dwLength))
1129 {
1130 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
1131 return FALSE;
1132 }
1133 }
1134
1135 /* Create user hive name */
1136 wcscat(szUserHivePath, L"\\");
1137 wcscat(szUserHivePath, lpProfileInfo->lpUserName);
1138 wcscat(szUserHivePath, L"\\ntuser.dat");
1139 DPRINT("szUserHivePath: %S\n", szUserHivePath);
1140
1141 /* Create user profile directory if needed */
1142 if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES)
1143 {
1144 /* Get user sid */
1145 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) ||
1146 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1147 {
1148 DPRINT1 ("GetTokenInformation() failed\n");
1149 return FALSE;
1150 }
1151
1152 UserSid = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, dwLength);
1153 if (!UserSid)
1154 {
1155 DPRINT1("HeapAlloc() failed\n");
1156 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1157 goto cleanup;
1158 }
1159
1160 if (!GetTokenInformation(hToken, TokenUser, UserSid, dwLength, &dwLength))
1161 {
1162 DPRINT1("GetTokenInformation() failed\n");
1163 goto cleanup;
1164 }
1165
1166 /* Get user name */
1167 do
1168 {
1169 if (UserNameLength > 0)
1170 {
1171 HeapFree(GetProcessHeap(), 0, UserName);
1172 UserName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, UserNameLength * sizeof(WCHAR));
1173 if (!UserName)
1174 {
1175 DPRINT1("HeapAlloc() failed\n");
1176 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1177 goto cleanup;
1178 }
1179 }
1180 if (DomainLength > 0)
1181 {
1182 HeapFree(GetProcessHeap(), 0, Domain);
1183 Domain = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, DomainLength * sizeof(WCHAR));
1184 if (!Domain)
1185 {
1186 DPRINT1("HeapAlloc() failed\n");
1187 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1188 goto cleanup;
1189 }
1190 }
1191 ret = LookupAccountSidW(NULL,
1192 UserSid->User.Sid,
1193 UserName,
1194 &UserNameLength,
1195 Domain,
1196 &DomainLength,
1197 &AccountType);
1198 } while (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
1199
1200 if (!ret)
1201 {
1202 DPRINT1("LookupAccountSidW() failed\n");
1203 goto cleanup;
1204 }
1205
1206 /* Create profile */
1207 /* FIXME: ignore Domain? */
1208 DPRINT("UserName %S, Domain %S\n", UserName, Domain);
1209 ret = CreateUserProfileW(UserSid->User.Sid, UserName);
1210 if (!ret)
1211 {
1212 DPRINT1("CreateUserProfileW() failed\n");
1213 goto cleanup;
1214 }
1215 }
1216
1217 /* Get user SID string */
1218 ret = GetUserSidStringFromToken(hToken, &SidString);
1219 if (!ret)
1220 {
1221 DPRINT1("GetUserSidFromToken() failed\n");
1222 goto cleanup;
1223 }
1224 ret = FALSE;
1225
1226 /* Acquire restore privilege */
1227 if (!AcquireRemoveRestorePrivilege(TRUE))
1228 {
1229 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1230 goto cleanup;
1231 }
1232
1233 /* Load user registry hive */
1234 Error = RegLoadKeyW(HKEY_USERS,
1235 SidString.Buffer,
1236 szUserHivePath);
1237 AcquireRemoveRestorePrivilege(FALSE);
1238
1239 /* HACK: Do not fail if the profile has already been loaded! */
1240 if (Error == ERROR_SHARING_VIOLATION)
1241 Error = ERROR_SUCCESS;
1242
1243 if (Error != ERROR_SUCCESS)
1244 {
1245 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error);
1246 SetLastError((DWORD)Error);
1247 goto cleanup;
1248 }
1249
1250 /* Open future HKEY_CURRENT_USER */
1251 Error = RegOpenKeyExW(HKEY_USERS,
1252 SidString.Buffer,
1253 0,
1254 MAXIMUM_ALLOWED,
1255 (PHKEY)&lpProfileInfo->hProfile);
1256 if (Error != ERROR_SUCCESS)
1257 {
1258 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
1259 SetLastError((DWORD)Error);
1260 goto cleanup;
1261 }
1262
1263 ret = TRUE;
1264
1265 cleanup:
1266 HeapFree(GetProcessHeap(), 0, UserSid);
1267 HeapFree(GetProcessHeap(), 0, UserName);
1268 HeapFree(GetProcessHeap(), 0, Domain);
1269 RtlFreeUnicodeString(&SidString);
1270
1271 DPRINT("LoadUserProfileW() done\n");
1272 return ret;
1273 }
1274
1275
1276 BOOL
1277 WINAPI
1278 UnloadUserProfile(HANDLE hToken,
1279 HANDLE hProfile)
1280 {
1281 UNICODE_STRING SidString;
1282 LONG Error;
1283
1284 DPRINT("UnloadUserProfile() called\n");
1285
1286 if (hProfile == NULL)
1287 {
1288 DPRINT1("Invalid profile handle\n");
1289 SetLastError(ERROR_INVALID_PARAMETER);
1290 return FALSE;
1291 }
1292
1293 RegCloseKey(hProfile);
1294
1295 if (!GetUserSidStringFromToken(hToken,
1296 &SidString))
1297 {
1298 DPRINT1("GetUserSidFromToken() failed\n");
1299 return FALSE;
1300 }
1301
1302 DPRINT("SidString: '%wZ'\n", &SidString);
1303
1304 /* Acquire restore privilege */
1305 if (!AcquireRemoveRestorePrivilege(TRUE))
1306 {
1307 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1308 RtlFreeUnicodeString(&SidString);
1309 return FALSE;
1310 }
1311
1312 /* HACK */
1313 {
1314 HKEY hUserKey;
1315
1316 Error = RegOpenKeyExW(HKEY_USERS,
1317 SidString.Buffer,
1318 0,
1319 KEY_WRITE,
1320 &hUserKey);
1321 if (Error == ERROR_SUCCESS)
1322 {
1323 RegDeleteKeyW(hUserKey,
1324 L"Volatile Environment");
1325
1326 RegCloseKey(hUserKey);
1327 }
1328 }
1329 /* End of HACK */
1330
1331 /* Unload the hive */
1332 Error = RegUnLoadKeyW(HKEY_USERS,
1333 SidString.Buffer);
1334
1335 /* Remove restore privilege */
1336 AcquireRemoveRestorePrivilege(FALSE);
1337
1338 if (Error != ERROR_SUCCESS)
1339 {
1340 DPRINT1("RegUnLoadKeyW() failed (Error %ld)\n", Error);
1341 RtlFreeUnicodeString(&SidString);
1342 SetLastError((DWORD)Error);
1343 return FALSE;
1344 }
1345
1346 RtlFreeUnicodeString(&SidString);
1347
1348 DPRINT("UnloadUserProfile() done\n");
1349
1350 return TRUE;
1351 }
1352
1353
1354 BOOL
1355 WINAPI
1356 DeleteProfileW(LPCWSTR lpSidString,
1357 LPCWSTR lpProfilePath,
1358 LPCWSTR lpComputerName)
1359 {
1360 DPRINT1("DeleteProfileW() not implemented!\n");
1361 return FALSE;
1362 }
1363
1364
1365 BOOL
1366 WINAPI
1367 DeleteProfileA(LPCSTR lpSidString,
1368 LPCSTR lpProfilePath,
1369 LPCSTR lpComputerName)
1370 {
1371 BOOL bResult;
1372 UNICODE_STRING SidString, ProfilePath, ComputerName;
1373
1374 DPRINT("DeleteProfileA() called\n");
1375
1376 /* Conversion to UNICODE */
1377 if (lpSidString)
1378 RtlCreateUnicodeStringFromAsciiz(&SidString,
1379 (LPSTR)lpSidString);
1380
1381 if (lpProfilePath)
1382 RtlCreateUnicodeStringFromAsciiz(&ProfilePath,
1383 (LPSTR)lpProfilePath);
1384
1385 if (lpComputerName)
1386 RtlCreateUnicodeStringFromAsciiz(&ComputerName,
1387 (LPSTR)lpComputerName);
1388
1389 /* Call the UNICODE function */
1390 bResult = DeleteProfileW(SidString.Buffer,
1391 ProfilePath.Buffer,
1392 ComputerName.Buffer);
1393
1394 /* Memory cleanup */
1395 if (lpSidString)
1396 RtlFreeUnicodeString(&SidString);
1397
1398 if (lpProfilePath)
1399 RtlFreeUnicodeString(&ProfilePath);
1400
1401 if (lpComputerName)
1402 RtlFreeUnicodeString(&ComputerName);
1403
1404 return bResult;
1405 }
1406
1407
1408 BOOL
1409 WINAPI
1410 GetProfileType(OUT PDWORD pdwFlags)
1411 {
1412 DPRINT1("GetProfileType() not implemented!\n");
1413 return FALSE;
1414 }
1415
1416 /* EOF */