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