[USERENV]
[reactos.git] / reactos / 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: lib/userenv/profile.c
22 * PURPOSE: User profile code
23 * PROGRAMMERS: Eric Kohl
24 * Hervé Poussineau
25 */
26
27 #include <precomp.h>
28
29 #define NDEBUG
30 #include <debug.h>
31
32
33 /* FUNCTIONS ***************************************************************/
34
35 BOOL
36 AppendSystemPostfix(LPWSTR lpName,
37 DWORD dwMaxLength)
38 {
39 WCHAR szSystemRoot[MAX_PATH];
40 LPWSTR lpszPostfix;
41 LPWSTR lpszPtr;
42
43 /* Build profile name postfix */
44 if (!ExpandEnvironmentStringsW(L"%SystemRoot%",
45 szSystemRoot,
46 MAX_PATH))
47 {
48 DPRINT1("Error: %lu\n", GetLastError());
49 return FALSE;
50 }
51
52 _wcsupr(szSystemRoot);
53
54 /* Get name postfix */
55 szSystemRoot[2] = L'.';
56 lpszPostfix = &szSystemRoot[2];
57 lpszPtr = lpszPostfix;
58 while (*lpszPtr != (WCHAR)0)
59 {
60 if (*lpszPtr == L'\\')
61 *lpszPtr = '_';
62 lpszPtr++;
63 }
64
65 if (wcslen(lpName) + wcslen(lpszPostfix) + 1 >= dwMaxLength)
66 {
67 DPRINT1("Error: buffer overflow\n");
68 SetLastError(ERROR_BUFFER_OVERFLOW);
69 return FALSE;
70 }
71
72 wcscat(lpName, lpszPostfix);
73
74 return TRUE;
75 }
76
77
78 BOOL
79 WINAPI
80 CreateUserProfileA(PSID Sid,
81 LPCSTR lpUserName)
82 {
83 UNICODE_STRING UserName;
84 BOOL bResult;
85 NTSTATUS Status;
86
87 Status = RtlCreateUnicodeStringFromAsciiz(&UserName,
88 (LPSTR)lpUserName);
89 if (!NT_SUCCESS(Status))
90 {
91 SetLastError(RtlNtStatusToDosError(Status));
92 return FALSE;
93 }
94
95 bResult = CreateUserProfileW(Sid, UserName.Buffer);
96
97 RtlFreeUnicodeString(&UserName);
98
99 return bResult;
100 }
101
102
103 static
104 BOOL
105 AcquireRemoveRestorePrivilege(IN BOOL bAcquire)
106 {
107 BOOL bRet = FALSE;
108 HANDLE Token;
109 TOKEN_PRIVILEGES TokenPriv;
110
111 DPRINT("AcquireRemoveRestorePrivilege(%d)\n", bAcquire);
112
113 if (OpenProcessToken(GetCurrentProcess(),
114 TOKEN_ADJUST_PRIVILEGES,
115 &Token))
116 {
117 TokenPriv.PrivilegeCount = 1;
118 TokenPriv.Privileges[0].Attributes = (bAcquire ? SE_PRIVILEGE_ENABLED : 0);
119
120 if (LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &TokenPriv.Privileges[0].Luid))
121 {
122 bRet = AdjustTokenPrivileges(Token, FALSE, &TokenPriv, 0, NULL, NULL);
123
124 if (!bRet)
125 {
126 DPRINT1("AdjustTokenPrivileges() failed with error %lu\n", GetLastError());
127 }
128 else if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
129 {
130 DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
131 bRet = FALSE;
132 }
133 }
134 else
135 {
136 DPRINT1("LookupPrivilegeValue() failed with error %lu\n", GetLastError());
137 }
138
139 CloseHandle(Token);
140 }
141 else
142 {
143 DPRINT1("OpenProcessToken() failed with error %lu\n", GetLastError());
144 }
145
146 return bRet;
147 }
148
149
150 BOOL
151 WINAPI
152 CreateUserProfileW(PSID Sid,
153 LPCWSTR lpUserName)
154 {
155 WCHAR szRawProfilesPath[MAX_PATH];
156 WCHAR szProfilesPath[MAX_PATH];
157 WCHAR szUserProfilePath[MAX_PATH];
158 WCHAR szDefaultUserPath[MAX_PATH];
159 WCHAR szUserProfileName[MAX_PATH];
160 WCHAR szBuffer[MAX_PATH];
161 LPWSTR SidString;
162 DWORD dwLength;
163 DWORD dwDisposition;
164 UINT i;
165 HKEY hKey;
166 BOOL bRet = TRUE;
167 LONG Error;
168
169 DPRINT("CreateUserProfileW() called\n");
170
171 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
172 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
173 0,
174 KEY_QUERY_VALUE,
175 &hKey);
176 if (Error != ERROR_SUCCESS)
177 {
178 DPRINT1("Error: %lu\n", Error);
179 SetLastError((DWORD)Error);
180 return FALSE;
181 }
182
183 /* Get profiles path */
184 dwLength = MAX_PATH * sizeof(WCHAR);
185 Error = RegQueryValueExW(hKey,
186 L"ProfilesDirectory",
187 NULL,
188 NULL,
189 (LPBYTE)szRawProfilesPath,
190 &dwLength);
191 if (Error != ERROR_SUCCESS)
192 {
193 DPRINT1("Error: %lu\n", Error);
194 RegCloseKey(hKey);
195 SetLastError((DWORD)Error);
196 return FALSE;
197 }
198
199 /* Expand it */
200 if (!ExpandEnvironmentStringsW(szRawProfilesPath,
201 szProfilesPath,
202 MAX_PATH))
203 {
204 DPRINT1("Error: %lu\n", GetLastError());
205 RegCloseKey(hKey);
206 return FALSE;
207 }
208
209 /* create the profiles directory if it does not yet exist */
210 if (!CreateDirectoryW(szProfilesPath, NULL))
211 {
212 if (GetLastError() != ERROR_ALREADY_EXISTS)
213 {
214 DPRINT1("Error: %lu\n", GetLastError());
215 return FALSE;
216 }
217 }
218
219 /* Get default user path */
220 dwLength = MAX_PATH * sizeof(WCHAR);
221 Error = RegQueryValueExW(hKey,
222 L"DefaultUserProfile",
223 NULL,
224 NULL,
225 (LPBYTE)szBuffer,
226 &dwLength);
227 if (Error != ERROR_SUCCESS)
228 {
229 DPRINT1("Error: %lu\n", Error);
230 RegCloseKey(hKey);
231 SetLastError((DWORD)Error);
232 return FALSE;
233 }
234
235 RegCloseKey (hKey);
236
237 wcscpy(szUserProfileName, lpUserName);
238
239 wcscpy(szUserProfilePath, szProfilesPath);
240 wcscat(szUserProfilePath, L"\\");
241 wcscat(szUserProfilePath, szUserProfileName);
242
243 wcscpy(szDefaultUserPath, szProfilesPath);
244 wcscat(szDefaultUserPath, L"\\");
245 wcscat(szDefaultUserPath, szBuffer);
246
247 /* Create user profile directory */
248 if (!CreateDirectoryW(szUserProfilePath, NULL))
249 {
250 if (GetLastError() != ERROR_ALREADY_EXISTS)
251 {
252 DPRINT1("Error: %lu\n", GetLastError());
253 return FALSE;
254 }
255
256 for (i = 0; i < 1000; i++)
257 {
258 swprintf(szUserProfileName, L"%s.%03u", lpUserName, i);
259
260 wcscpy(szUserProfilePath, szProfilesPath);
261 wcscat(szUserProfilePath, L"\\");
262 wcscat(szUserProfilePath, szUserProfileName);
263
264 if (CreateDirectoryW(szUserProfilePath, NULL))
265 break;
266
267 if (GetLastError() != ERROR_ALREADY_EXISTS)
268 {
269 DPRINT1("Error: %lu\n", GetLastError());
270 return FALSE;
271 }
272 }
273 }
274
275 /* Copy default user directory */
276 if (!CopyDirectory(szUserProfilePath, szDefaultUserPath))
277 {
278 DPRINT1("Error: %lu\n", GetLastError());
279 return FALSE;
280 }
281
282 /* Add profile to profile list */
283 if (!ConvertSidToStringSidW(Sid,
284 &SidString))
285 {
286 DPRINT1("Error: %lu\n", GetLastError());
287 return FALSE;
288 }
289
290 wcscpy(szBuffer,
291 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
292 wcscat(szBuffer, SidString);
293
294 /* Create user profile key */
295 Error = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
296 szBuffer,
297 0,
298 NULL,
299 REG_OPTION_NON_VOLATILE,
300 KEY_ALL_ACCESS,
301 NULL,
302 &hKey,
303 &dwDisposition);
304 if (Error != ERROR_SUCCESS)
305 {
306 DPRINT1("Error: %lu\n", Error);
307 bRet = FALSE;
308 goto Done;
309 }
310
311 /* Create non-expanded user profile path */
312 wcscpy(szBuffer, szRawProfilesPath);
313 wcscat(szBuffer, L"\\");
314 wcscat(szBuffer, szUserProfileName);
315
316 /* Set 'ProfileImagePath' value (non-expanded) */
317 Error = RegSetValueExW(hKey,
318 L"ProfileImagePath",
319 0,
320 REG_EXPAND_SZ,
321 (LPBYTE)szBuffer,
322 (wcslen (szBuffer) + 1) * sizeof(WCHAR));
323 if (Error != ERROR_SUCCESS)
324 {
325 DPRINT1("Error: %lu\n", Error);
326 RegCloseKey(hKey);
327 bRet = FALSE;
328 goto Done;
329 }
330
331 /* Set 'Sid' value */
332 Error = RegSetValueExW(hKey,
333 L"Sid",
334 0,
335 REG_BINARY,
336 Sid,
337 GetLengthSid(Sid));
338 if (Error != ERROR_SUCCESS)
339 {
340 DPRINT1("Error: %lu\n", Error);
341 RegCloseKey(hKey);
342 bRet = FALSE;
343 goto Done;
344 }
345
346 RegCloseKey(hKey);
347
348 /* Create user hive name */
349 wcscpy(szBuffer, szUserProfilePath);
350 wcscat(szBuffer, L"\\ntuser.dat");
351
352 /* Acquire restore privilege */
353 if (!AcquireRemoveRestorePrivilege(TRUE))
354 {
355 Error = GetLastError();
356 DPRINT1("Error: %lu\n", Error);
357 bRet = FALSE;
358 goto Done;
359 }
360
361 /* Create new user hive */
362 Error = RegLoadKeyW(HKEY_USERS,
363 SidString,
364 szBuffer);
365 AcquireRemoveRestorePrivilege(FALSE);
366 if (Error != ERROR_SUCCESS)
367 {
368 DPRINT1("Error: %lu\n", Error);
369 bRet = FALSE;
370 goto Done;
371 }
372
373 /* Initialize user hive */
374 if (!CreateUserHive(SidString, szUserProfilePath))
375 {
376 Error = GetLastError();
377 DPRINT1("Error: %lu\n", Error);
378 bRet = FALSE;
379 }
380
381 /* Unload the hive */
382 AcquireRemoveRestorePrivilege(TRUE);
383 RegUnLoadKeyW(HKEY_USERS, SidString);
384 AcquireRemoveRestorePrivilege(FALSE);
385
386 Done:
387 LocalFree((HLOCAL)SidString);
388 SetLastError((DWORD)Error);
389
390 DPRINT("CreateUserProfileW() done\n");
391
392 return bRet;
393 }
394
395
396 BOOL
397 WINAPI
398 GetAllUsersProfileDirectoryA(LPSTR lpProfileDir,
399 LPDWORD lpcchSize)
400 {
401 LPWSTR lpBuffer;
402 BOOL bResult;
403
404 lpBuffer = GlobalAlloc(GMEM_FIXED,
405 *lpcchSize * sizeof(WCHAR));
406 if (lpBuffer == NULL)
407 return FALSE;
408
409 bResult = GetAllUsersProfileDirectoryW(lpBuffer,
410 lpcchSize);
411 if (bResult)
412 {
413 WideCharToMultiByte(CP_ACP,
414 0,
415 lpBuffer,
416 -1,
417 lpProfileDir,
418 *lpcchSize,
419 NULL,
420 NULL);
421 }
422
423 GlobalFree(lpBuffer);
424
425 return bResult;
426 }
427
428
429 BOOL
430 WINAPI
431 GetAllUsersProfileDirectoryW(LPWSTR lpProfileDir,
432 LPDWORD lpcchSize)
433 {
434 WCHAR szProfilePath[MAX_PATH];
435 WCHAR szBuffer[MAX_PATH];
436 DWORD dwLength;
437 HKEY hKey;
438 LONG Error;
439
440 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
441 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
442 0,
443 KEY_QUERY_VALUE,
444 &hKey);
445 if (Error != ERROR_SUCCESS)
446 {
447 DPRINT1("Error: %lu\n", Error);
448 SetLastError((DWORD)Error);
449 return FALSE;
450 }
451
452 /* Get profiles path */
453 dwLength = sizeof(szBuffer);
454 Error = RegQueryValueExW(hKey,
455 L"ProfilesDirectory",
456 NULL,
457 NULL,
458 (LPBYTE)szBuffer,
459 &dwLength);
460 if (Error != ERROR_SUCCESS)
461 {
462 DPRINT1("Error: %lu\n", Error);
463 RegCloseKey(hKey);
464 SetLastError((DWORD)Error);
465 return FALSE;
466 }
467
468 /* Expand it */
469 if (!ExpandEnvironmentStringsW(szBuffer,
470 szProfilePath,
471 MAX_PATH))
472 {
473 DPRINT1("Error: %lu\n", GetLastError());
474 RegCloseKey (hKey);
475 return FALSE;
476 }
477
478 /* Get 'AllUsersProfile' name */
479 dwLength = sizeof(szBuffer);
480 Error = RegQueryValueExW(hKey,
481 L"AllUsersProfile",
482 NULL,
483 NULL,
484 (LPBYTE)szBuffer,
485 &dwLength);
486 if (Error != ERROR_SUCCESS)
487 {
488 DPRINT1("Error: %lu\n", Error);
489 RegCloseKey(hKey);
490 SetLastError((DWORD)Error);
491 return FALSE;
492 }
493
494 RegCloseKey (hKey);
495
496 wcscat(szProfilePath, L"\\");
497 wcscat(szProfilePath, szBuffer);
498
499 dwLength = wcslen(szProfilePath) + 1;
500 if (lpProfileDir != NULL)
501 {
502 if (*lpcchSize < dwLength)
503 {
504 *lpcchSize = dwLength;
505 SetLastError(ERROR_INSUFFICIENT_BUFFER);
506 return FALSE;
507 }
508
509 wcscpy(lpProfileDir, szProfilePath);
510 }
511
512 *lpcchSize = dwLength;
513
514 return TRUE;
515 }
516
517
518 BOOL
519 WINAPI
520 GetDefaultUserProfileDirectoryA(LPSTR lpProfileDir,
521 LPDWORD lpcchSize)
522 {
523 LPWSTR lpBuffer;
524 BOOL bResult;
525
526 lpBuffer = GlobalAlloc(GMEM_FIXED,
527 *lpcchSize * sizeof(WCHAR));
528 if (lpBuffer == NULL)
529 return FALSE;
530
531 bResult = GetDefaultUserProfileDirectoryW(lpBuffer,
532 lpcchSize);
533 if (bResult)
534 {
535 WideCharToMultiByte(CP_ACP,
536 0,
537 lpBuffer,
538 -1,
539 lpProfileDir,
540 *lpcchSize,
541 NULL,
542 NULL);
543 }
544
545 GlobalFree(lpBuffer);
546
547 return bResult;
548 }
549
550
551 BOOL
552 WINAPI
553 GetDefaultUserProfileDirectoryW(LPWSTR lpProfileDir,
554 LPDWORD lpcchSize)
555 {
556 WCHAR szProfilePath[MAX_PATH];
557 WCHAR szBuffer[MAX_PATH];
558 DWORD dwLength;
559 HKEY hKey;
560 LONG Error;
561
562 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
563 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
564 0,
565 KEY_QUERY_VALUE,
566 &hKey);
567 if (Error != ERROR_SUCCESS)
568 {
569 DPRINT1("Error: %lu\n", Error);
570 SetLastError((DWORD)Error);
571 return FALSE;
572 }
573
574 /* Get profiles path */
575 dwLength = sizeof(szBuffer);
576 Error = RegQueryValueExW(hKey,
577 L"ProfilesDirectory",
578 NULL,
579 NULL,
580 (LPBYTE)szBuffer,
581 &dwLength);
582 if (Error != ERROR_SUCCESS)
583 {
584 DPRINT1("Error: %lu\n", Error);
585 RegCloseKey(hKey);
586 SetLastError((DWORD)Error);
587 return FALSE;
588 }
589
590 /* Expand it */
591 if (!ExpandEnvironmentStringsW(szBuffer,
592 szProfilePath,
593 MAX_PATH))
594 {
595 DPRINT1("Error: %lu\n", GetLastError());
596 RegCloseKey(hKey);
597 return FALSE;
598 }
599
600 /* Get 'DefaultUserProfile' name */
601 dwLength = sizeof(szBuffer);
602 Error = RegQueryValueExW(hKey,
603 L"DefaultUserProfile",
604 NULL,
605 NULL,
606 (LPBYTE)szBuffer,
607 &dwLength);
608 if (Error != ERROR_SUCCESS)
609 {
610 DPRINT1("Error: %lu\n", Error);
611 RegCloseKey(hKey);
612 SetLastError((DWORD)Error);
613 return FALSE;
614 }
615
616 RegCloseKey(hKey);
617
618 wcscat(szProfilePath, L"\\");
619 wcscat(szProfilePath, szBuffer);
620
621 dwLength = wcslen(szProfilePath) + 1;
622 if (lpProfileDir != NULL)
623 {
624 if (*lpcchSize < dwLength)
625 {
626 *lpcchSize = dwLength;
627 SetLastError(ERROR_INSUFFICIENT_BUFFER);
628 return FALSE;
629 }
630
631 wcscpy(lpProfileDir, szProfilePath);
632 }
633
634 *lpcchSize = dwLength;
635
636 return TRUE;
637 }
638
639
640 BOOL
641 WINAPI
642 GetProfilesDirectoryA(LPSTR lpProfileDir,
643 LPDWORD lpcchSize)
644 {
645 LPWSTR lpBuffer;
646 BOOL bResult;
647
648 lpBuffer = GlobalAlloc(GMEM_FIXED,
649 *lpcchSize * sizeof(WCHAR));
650 if (lpBuffer == NULL)
651 return FALSE;
652
653 bResult = GetProfilesDirectoryW(lpBuffer,
654 lpcchSize);
655 if (bResult)
656 {
657 WideCharToMultiByte(CP_ACP,
658 0,
659 lpBuffer,
660 -1,
661 lpProfileDir,
662 *lpcchSize,
663 NULL,
664 NULL);
665 }
666
667 GlobalFree(lpBuffer);
668
669 return bResult;
670 }
671
672
673 BOOL
674 WINAPI
675 GetProfilesDirectoryW(LPWSTR lpProfilesDir,
676 LPDWORD lpcchSize)
677 {
678 WCHAR szProfilesPath[MAX_PATH];
679 WCHAR szBuffer[MAX_PATH];
680 DWORD dwLength;
681 HKEY hKey;
682 LONG Error;
683
684 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
685 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
686 0,
687 KEY_QUERY_VALUE,
688 &hKey);
689 if (Error != ERROR_SUCCESS)
690 {
691 DPRINT1("Error: %lu\n", Error);
692 SetLastError((DWORD)Error);
693 return FALSE;
694 }
695
696 /* Get profiles path */
697 dwLength = sizeof(szBuffer);
698 Error = RegQueryValueExW(hKey,
699 L"ProfilesDirectory",
700 NULL,
701 NULL,
702 (LPBYTE)szBuffer,
703 &dwLength);
704 if (Error != ERROR_SUCCESS)
705 {
706 DPRINT1("Error: %lu\n", Error);
707 RegCloseKey(hKey);
708 SetLastError((DWORD)Error);
709 return FALSE;
710 }
711
712 RegCloseKey(hKey);
713
714 /* Expand it */
715 if (!ExpandEnvironmentStringsW(szBuffer,
716 szProfilesPath,
717 MAX_PATH))
718 {
719 DPRINT1("Error: %lu\n", GetLastError());
720 return FALSE;
721 }
722
723 dwLength = wcslen (szProfilesPath) + 1;
724 if (lpProfilesDir != NULL)
725 {
726 if (*lpcchSize < dwLength)
727 {
728 *lpcchSize = dwLength;
729 SetLastError(ERROR_INSUFFICIENT_BUFFER);
730 return FALSE;
731 }
732
733 wcscpy(lpProfilesDir, szProfilesPath);
734 }
735
736 *lpcchSize = dwLength;
737
738 return TRUE;
739 }
740
741
742 BOOL
743 WINAPI
744 GetUserProfileDirectoryA(HANDLE hToken,
745 LPSTR lpProfileDir,
746 LPDWORD lpcchSize)
747 {
748 LPWSTR lpBuffer;
749 BOOL bResult;
750
751 lpBuffer = GlobalAlloc(GMEM_FIXED,
752 *lpcchSize * sizeof(WCHAR));
753 if (lpBuffer == NULL)
754 return FALSE;
755
756 bResult = GetUserProfileDirectoryW(hToken,
757 lpBuffer,
758 lpcchSize);
759 if (bResult)
760 {
761 WideCharToMultiByte(CP_ACP,
762 0,
763 lpBuffer,
764 -1,
765 lpProfileDir,
766 *lpcchSize,
767 NULL,
768 NULL);
769 }
770
771 GlobalFree(lpBuffer);
772
773 return bResult;
774 }
775
776
777 BOOL
778 WINAPI
779 GetUserProfileDirectoryW(HANDLE hToken,
780 LPWSTR lpProfileDir,
781 LPDWORD lpcchSize)
782 {
783 UNICODE_STRING SidString;
784 WCHAR szKeyName[MAX_PATH];
785 WCHAR szRawImagePath[MAX_PATH];
786 WCHAR szImagePath[MAX_PATH];
787 DWORD dwLength;
788 HKEY hKey;
789 LONG Error;
790
791 if (!GetUserSidFromToken(hToken,
792 &SidString))
793 {
794 DPRINT1("GetUserSidFromToken() failed\n");
795 return FALSE;
796 }
797
798 DPRINT("SidString: '%wZ'\n", &SidString);
799
800 wcscpy(szKeyName,
801 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
802 wcscat(szKeyName,
803 SidString.Buffer);
804
805 RtlFreeUnicodeString(&SidString);
806
807 DPRINT("KeyName: '%S'\n", szKeyName);
808
809 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
810 szKeyName,
811 0,
812 KEY_QUERY_VALUE,
813 &hKey);
814 if (Error != ERROR_SUCCESS)
815 {
816 DPRINT1("Error: %lu\n", Error);
817 SetLastError((DWORD)Error);
818 return FALSE;
819 }
820
821 dwLength = sizeof(szRawImagePath);
822 Error = RegQueryValueExW(hKey,
823 L"ProfileImagePath",
824 NULL,
825 NULL,
826 (LPBYTE)szRawImagePath,
827 &dwLength);
828 if (Error != ERROR_SUCCESS)
829 {
830 DPRINT1("Error: %lu\n", Error);
831 RegCloseKey(hKey);
832 SetLastError((DWORD)Error);
833 return FALSE;
834 }
835
836 RegCloseKey(hKey);
837
838 DPRINT("RawImagePath: '%S'\n", szRawImagePath);
839
840 /* Expand it */
841 if (!ExpandEnvironmentStringsW(szRawImagePath,
842 szImagePath,
843 MAX_PATH))
844 {
845 DPRINT1 ("Error: %lu\n", GetLastError());
846 return FALSE;
847 }
848
849 DPRINT("ImagePath: '%S'\n", szImagePath);
850
851 dwLength = wcslen (szImagePath) + 1;
852 if (*lpcchSize < dwLength)
853 {
854 *lpcchSize = dwLength;
855 SetLastError(ERROR_INSUFFICIENT_BUFFER);
856 return FALSE;
857 }
858
859 *lpcchSize = dwLength;
860 wcscpy(lpProfileDir, szImagePath);
861
862 return TRUE;
863 }
864
865
866 static
867 BOOL
868 CheckForLoadedProfile(HANDLE hToken)
869 {
870 UNICODE_STRING SidString;
871 HKEY hKey;
872
873 DPRINT("CheckForLoadedProfile() called\n");
874
875 if (!GetUserSidFromToken(hToken,
876 &SidString))
877 {
878 DPRINT1("GetUserSidFromToken() failed\n");
879 return FALSE;
880 }
881
882 if (RegOpenKeyExW(HKEY_USERS,
883 SidString.Buffer,
884 0,
885 MAXIMUM_ALLOWED,
886 &hKey))
887 {
888 DPRINT("Profile not loaded\n");
889 RtlFreeUnicodeString(&SidString);
890 return FALSE;
891 }
892
893 RegCloseKey(hKey);
894
895 RtlFreeUnicodeString(&SidString);
896
897 DPRINT("Profile already loaded\n");
898
899 return TRUE;
900 }
901
902
903 BOOL
904 WINAPI
905 LoadUserProfileA(HANDLE hToken,
906 LPPROFILEINFOA lpProfileInfo)
907 {
908 DPRINT ("LoadUserProfileA() not implemented\n");
909 return FALSE;
910 }
911
912
913 BOOL
914 WINAPI
915 LoadUserProfileW(IN HANDLE hToken,
916 IN OUT LPPROFILEINFOW lpProfileInfo)
917 {
918 WCHAR szUserHivePath[MAX_PATH];
919 LPWSTR UserName = NULL, Domain = NULL;
920 DWORD UserNameLength = 0, DomainLength = 0;
921 PTOKEN_USER UserSid = NULL;
922 SID_NAME_USE AccountType;
923 UNICODE_STRING SidString = { 0, 0, NULL };
924 LONG Error;
925 BOOL ret = FALSE;
926 DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
927
928 DPRINT("LoadUserProfileW() called\n");
929
930 /* Check profile info */
931 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOW)) ||
932 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
933 {
934 SetLastError(ERROR_INVALID_PARAMETER);
935 return TRUE;
936 }
937
938 /* Don't load a profile twice */
939 if (CheckForLoadedProfile(hToken))
940 {
941 DPRINT ("Profile already loaded\n");
942 lpProfileInfo->hProfile = NULL;
943 return TRUE;
944 }
945
946 if (lpProfileInfo->lpProfilePath)
947 {
948 wcscpy(szUserHivePath, lpProfileInfo->lpProfilePath);
949 }
950 else
951 {
952 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
953 if (!GetProfilesDirectoryW(szUserHivePath, &dwLength))
954 {
955 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
956 return FALSE;
957 }
958 }
959
960 /* Create user hive name */
961 wcscat(szUserHivePath, L"\\");
962 wcscat(szUserHivePath, lpProfileInfo->lpUserName);
963 wcscat(szUserHivePath, L"\\ntuser.dat");
964 DPRINT("szUserHivePath: %S\n", szUserHivePath);
965
966 /* Create user profile directory if needed */
967 if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES)
968 {
969 /* Get user sid */
970 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) ||
971 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
972 {
973 DPRINT1 ("GetTokenInformation() failed\n");
974 return FALSE;
975 }
976
977 UserSid = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, dwLength);
978 if (!UserSid)
979 {
980 DPRINT1("HeapAlloc() failed\n");
981 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
982 goto cleanup;
983 }
984
985 if (!GetTokenInformation(hToken, TokenUser, UserSid, dwLength, &dwLength))
986 {
987 DPRINT1("GetTokenInformation() failed\n");
988 goto cleanup;
989 }
990
991 /* Get user name */
992 do
993 {
994 if (UserNameLength > 0)
995 {
996 HeapFree(GetProcessHeap(), 0, UserName);
997 UserName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, UserNameLength * sizeof(WCHAR));
998 if (!UserName)
999 {
1000 DPRINT1("HeapAlloc() failed\n");
1001 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1002 goto cleanup;
1003 }
1004 }
1005 if (DomainLength > 0)
1006 {
1007 HeapFree(GetProcessHeap(), 0, Domain);
1008 Domain = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, DomainLength * sizeof(WCHAR));
1009 if (!Domain)
1010 {
1011 DPRINT1("HeapAlloc() failed\n");
1012 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1013 goto cleanup;
1014 }
1015 }
1016 ret = LookupAccountSidW(NULL,
1017 UserSid->User.Sid,
1018 UserName,
1019 &UserNameLength,
1020 Domain,
1021 &DomainLength,
1022 &AccountType);
1023 } while (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
1024
1025 if (!ret)
1026 {
1027 DPRINT1("LookupAccountSidW() failed\n");
1028 goto cleanup;
1029 }
1030
1031 /* Create profile */
1032 /* FIXME: ignore Domain? */
1033 DPRINT("UserName %S, Domain %S\n", UserName, Domain);
1034 ret = CreateUserProfileW(UserSid->User.Sid, UserName);
1035 if (!ret)
1036 {
1037 DPRINT1("CreateUserProfileW() failed\n");
1038 goto cleanup;
1039 }
1040 }
1041
1042 /* Get user SID string */
1043 ret = GetUserSidFromToken(hToken, &SidString);
1044 if (!ret)
1045 {
1046 DPRINT1("GetUserSidFromToken() failed\n");
1047 goto cleanup;
1048 }
1049 ret = FALSE;
1050
1051 /* Acquire restore privilege */
1052 if (!AcquireRemoveRestorePrivilege(TRUE))
1053 {
1054 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1055 goto cleanup;
1056 }
1057
1058 /* Load user registry hive */
1059 Error = RegLoadKeyW(HKEY_USERS,
1060 SidString.Buffer,
1061 szUserHivePath);
1062 AcquireRemoveRestorePrivilege(FALSE);
1063 if (Error != ERROR_SUCCESS)
1064 {
1065 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error);
1066 SetLastError((DWORD)Error);
1067 goto cleanup;
1068 }
1069
1070 /* Open future HKEY_CURRENT_USER */
1071 Error = RegOpenKeyExW(HKEY_USERS,
1072 SidString.Buffer,
1073 0,
1074 MAXIMUM_ALLOWED,
1075 (PHKEY)&lpProfileInfo->hProfile);
1076 if (Error != ERROR_SUCCESS)
1077 {
1078 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
1079 SetLastError((DWORD)Error);
1080 goto cleanup;
1081 }
1082
1083 ret = TRUE;
1084
1085 cleanup:
1086 HeapFree(GetProcessHeap(), 0, UserSid);
1087 HeapFree(GetProcessHeap(), 0, UserName);
1088 HeapFree(GetProcessHeap(), 0, Domain);
1089 RtlFreeUnicodeString(&SidString);
1090
1091 DPRINT("LoadUserProfileW() done\n");
1092 return ret;
1093 }
1094
1095
1096 BOOL
1097 WINAPI
1098 UnloadUserProfile(HANDLE hToken,
1099 HANDLE hProfile)
1100 {
1101 UNICODE_STRING SidString;
1102 LONG Error;
1103
1104 DPRINT("UnloadUserProfile() called\n");
1105
1106 if (hProfile == NULL)
1107 {
1108 DPRINT1("Invalide profile handle\n");
1109 SetLastError(ERROR_INVALID_PARAMETER);
1110 return FALSE;
1111 }
1112
1113 RegCloseKey(hProfile);
1114
1115 if (!GetUserSidFromToken(hToken,
1116 &SidString))
1117 {
1118 DPRINT1("GetUserSidFromToken() failed\n");
1119 return FALSE;
1120 }
1121
1122 DPRINT("SidString: '%wZ'\n", &SidString);
1123
1124 /* Acquire restore privilege */
1125 if (!AcquireRemoveRestorePrivilege(TRUE))
1126 {
1127 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1128 RtlFreeUnicodeString(&SidString);
1129 return FALSE;
1130 }
1131
1132 /* Unload the hive */
1133 Error = RegUnLoadKeyW(HKEY_USERS,
1134 SidString.Buffer);
1135
1136 /* Remove restore privilege */
1137 AcquireRemoveRestorePrivilege(FALSE);
1138
1139 if (Error != ERROR_SUCCESS)
1140 {
1141 DPRINT1("RegUnLoadKeyW() failed (Error %ld)\n", Error);
1142 RtlFreeUnicodeString(&SidString);
1143 SetLastError((DWORD)Error);
1144 return FALSE;
1145 }
1146
1147 RtlFreeUnicodeString(&SidString);
1148
1149 DPRINT("UnloadUserProfile() done\n");
1150
1151 return TRUE;
1152 }
1153
1154 BOOL
1155 WINAPI
1156 DeleteProfileW(LPCWSTR lpSidString,
1157 LPCWSTR lpProfilePath,
1158 LPCWSTR lpComputerName)
1159 {
1160 DPRINT1("DeleteProfileW() not implemented!\n");
1161 return FALSE;
1162 }
1163
1164 BOOL
1165 WINAPI
1166 DeleteProfileA(LPCSTR lpSidString,
1167 LPCSTR lpProfilePath,
1168 LPCSTR lpComputerName)
1169 {
1170 DPRINT1("DeleteProfileA() not implemented!\n");
1171 return FALSE;
1172 }
1173
1174 /* EOF */