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