* Sync up to trunk HEAD (r62285). Branch guys deserve the significant speedups too ;)
[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 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
468 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
469 0,
470 KEY_QUERY_VALUE,
471 &hKey);
472 if (Error != ERROR_SUCCESS)
473 {
474 DPRINT1("Error: %lu\n", Error);
475 SetLastError((DWORD)Error);
476 return FALSE;
477 }
478
479 /* Get profiles path */
480 dwLength = sizeof(szBuffer);
481 Error = RegQueryValueExW(hKey,
482 L"ProfilesDirectory",
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 /* Expand it */
496 if (!ExpandEnvironmentStringsW(szBuffer,
497 szProfilePath,
498 MAX_PATH))
499 {
500 DPRINT1("Error: %lu\n", GetLastError());
501 RegCloseKey (hKey);
502 return FALSE;
503 }
504
505 /* Get 'AllUsersProfile' name */
506 dwLength = sizeof(szBuffer);
507 Error = RegQueryValueExW(hKey,
508 L"AllUsersProfile",
509 NULL,
510 NULL,
511 (LPBYTE)szBuffer,
512 &dwLength);
513 if (Error != ERROR_SUCCESS)
514 {
515 DPRINT1("Error: %lu\n", Error);
516 RegCloseKey(hKey);
517 SetLastError((DWORD)Error);
518 return FALSE;
519 }
520
521 RegCloseKey (hKey);
522
523 wcscat(szProfilePath, L"\\");
524 wcscat(szProfilePath, szBuffer);
525
526 dwLength = wcslen(szProfilePath) + 1;
527 if (lpProfileDir != NULL)
528 {
529 if (*lpcchSize < dwLength)
530 {
531 *lpcchSize = dwLength;
532 SetLastError(ERROR_INSUFFICIENT_BUFFER);
533 return FALSE;
534 }
535
536 wcscpy(lpProfileDir, szProfilePath);
537 }
538
539 *lpcchSize = dwLength;
540
541 return TRUE;
542 }
543
544
545 BOOL
546 WINAPI
547 GetDefaultUserProfileDirectoryA(LPSTR lpProfileDir,
548 LPDWORD lpcchSize)
549 {
550 LPWSTR lpBuffer;
551 BOOL bResult;
552
553 lpBuffer = GlobalAlloc(GMEM_FIXED,
554 *lpcchSize * sizeof(WCHAR));
555 if (lpBuffer == NULL)
556 return FALSE;
557
558 bResult = GetDefaultUserProfileDirectoryW(lpBuffer,
559 lpcchSize);
560 if (bResult)
561 {
562 WideCharToMultiByte(CP_ACP,
563 0,
564 lpBuffer,
565 -1,
566 lpProfileDir,
567 *lpcchSize,
568 NULL,
569 NULL);
570 }
571
572 GlobalFree(lpBuffer);
573
574 return bResult;
575 }
576
577
578 BOOL
579 WINAPI
580 GetDefaultUserProfileDirectoryW(LPWSTR lpProfileDir,
581 LPDWORD lpcchSize)
582 {
583 WCHAR szProfilePath[MAX_PATH];
584 WCHAR szBuffer[MAX_PATH];
585 DWORD dwLength;
586 HKEY hKey;
587 LONG Error;
588
589 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
590 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
591 0,
592 KEY_QUERY_VALUE,
593 &hKey);
594 if (Error != ERROR_SUCCESS)
595 {
596 DPRINT1("Error: %lu\n", Error);
597 SetLastError((DWORD)Error);
598 return FALSE;
599 }
600
601 /* Get profiles path */
602 dwLength = sizeof(szBuffer);
603 Error = RegQueryValueExW(hKey,
604 L"ProfilesDirectory",
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 /* Expand it */
618 if (!ExpandEnvironmentStringsW(szBuffer,
619 szProfilePath,
620 MAX_PATH))
621 {
622 DPRINT1("Error: %lu\n", GetLastError());
623 RegCloseKey(hKey);
624 return FALSE;
625 }
626
627 /* Get 'DefaultUserProfile' name */
628 dwLength = sizeof(szBuffer);
629 Error = RegQueryValueExW(hKey,
630 L"DefaultUserProfile",
631 NULL,
632 NULL,
633 (LPBYTE)szBuffer,
634 &dwLength);
635 if (Error != ERROR_SUCCESS)
636 {
637 DPRINT1("Error: %lu\n", Error);
638 RegCloseKey(hKey);
639 SetLastError((DWORD)Error);
640 return FALSE;
641 }
642
643 RegCloseKey(hKey);
644
645 wcscat(szProfilePath, L"\\");
646 wcscat(szProfilePath, szBuffer);
647
648 dwLength = wcslen(szProfilePath) + 1;
649 if (lpProfileDir != NULL)
650 {
651 if (*lpcchSize < dwLength)
652 {
653 *lpcchSize = dwLength;
654 SetLastError(ERROR_INSUFFICIENT_BUFFER);
655 return FALSE;
656 }
657
658 wcscpy(lpProfileDir, szProfilePath);
659 }
660
661 *lpcchSize = dwLength;
662
663 return TRUE;
664 }
665
666
667 BOOL
668 WINAPI
669 GetProfilesDirectoryA(LPSTR lpProfileDir,
670 LPDWORD lpcchSize)
671 {
672 LPWSTR lpBuffer;
673 BOOL bResult;
674
675 lpBuffer = GlobalAlloc(GMEM_FIXED,
676 *lpcchSize * sizeof(WCHAR));
677 if (lpBuffer == NULL)
678 return FALSE;
679
680 bResult = GetProfilesDirectoryW(lpBuffer,
681 lpcchSize);
682 if (bResult)
683 {
684 WideCharToMultiByte(CP_ACP,
685 0,
686 lpBuffer,
687 -1,
688 lpProfileDir,
689 *lpcchSize,
690 NULL,
691 NULL);
692 }
693
694 GlobalFree(lpBuffer);
695
696 return bResult;
697 }
698
699
700 BOOL
701 WINAPI
702 GetProfilesDirectoryW(LPWSTR lpProfilesDir,
703 LPDWORD lpcchSize)
704 {
705 WCHAR szProfilesPath[MAX_PATH];
706 WCHAR szBuffer[MAX_PATH];
707 DWORD dwLength;
708 HKEY hKey;
709 LONG Error;
710
711 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
712 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
713 0,
714 KEY_QUERY_VALUE,
715 &hKey);
716 if (Error != ERROR_SUCCESS)
717 {
718 DPRINT1("Error: %lu\n", Error);
719 SetLastError((DWORD)Error);
720 return FALSE;
721 }
722
723 /* Get profiles path */
724 dwLength = sizeof(szBuffer);
725 Error = RegQueryValueExW(hKey,
726 L"ProfilesDirectory",
727 NULL,
728 NULL,
729 (LPBYTE)szBuffer,
730 &dwLength);
731 if (Error != ERROR_SUCCESS)
732 {
733 DPRINT1("Error: %lu\n", Error);
734 RegCloseKey(hKey);
735 SetLastError((DWORD)Error);
736 return FALSE;
737 }
738
739 RegCloseKey(hKey);
740
741 /* Expand it */
742 if (!ExpandEnvironmentStringsW(szBuffer,
743 szProfilesPath,
744 MAX_PATH))
745 {
746 DPRINT1("Error: %lu\n", GetLastError());
747 return FALSE;
748 }
749
750 dwLength = wcslen (szProfilesPath) + 1;
751 if (lpProfilesDir != NULL)
752 {
753 if (*lpcchSize < dwLength)
754 {
755 *lpcchSize = dwLength;
756 SetLastError(ERROR_INSUFFICIENT_BUFFER);
757 return FALSE;
758 }
759
760 wcscpy(lpProfilesDir, szProfilesPath);
761 }
762
763 *lpcchSize = dwLength;
764
765 return TRUE;
766 }
767
768
769 BOOL
770 WINAPI
771 GetUserProfileDirectoryA(HANDLE hToken,
772 LPSTR lpProfileDir,
773 LPDWORD lpcchSize)
774 {
775 LPWSTR lpBuffer;
776 BOOL bResult;
777
778 lpBuffer = GlobalAlloc(GMEM_FIXED,
779 *lpcchSize * sizeof(WCHAR));
780 if (lpBuffer == NULL)
781 return FALSE;
782
783 bResult = GetUserProfileDirectoryW(hToken,
784 lpBuffer,
785 lpcchSize);
786 if (bResult)
787 {
788 WideCharToMultiByte(CP_ACP,
789 0,
790 lpBuffer,
791 -1,
792 lpProfileDir,
793 *lpcchSize,
794 NULL,
795 NULL);
796 }
797
798 GlobalFree(lpBuffer);
799
800 return bResult;
801 }
802
803
804 BOOL
805 WINAPI
806 GetUserProfileDirectoryW(HANDLE hToken,
807 LPWSTR lpProfileDir,
808 LPDWORD lpcchSize)
809 {
810 UNICODE_STRING SidString;
811 WCHAR szKeyName[MAX_PATH];
812 WCHAR szRawImagePath[MAX_PATH];
813 WCHAR szImagePath[MAX_PATH];
814 DWORD dwLength;
815 HKEY hKey;
816 LONG Error;
817
818 if (!GetUserSidStringFromToken(hToken,
819 &SidString))
820 {
821 DPRINT1("GetUserSidFromToken() failed\n");
822 return FALSE;
823 }
824
825 DPRINT("SidString: '%wZ'\n", &SidString);
826
827 wcscpy(szKeyName,
828 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
829 wcscat(szKeyName,
830 SidString.Buffer);
831
832 RtlFreeUnicodeString(&SidString);
833
834 DPRINT("KeyName: '%S'\n", szKeyName);
835
836 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
837 szKeyName,
838 0,
839 KEY_QUERY_VALUE,
840 &hKey);
841 if (Error != ERROR_SUCCESS)
842 {
843 DPRINT1("Error: %lu\n", Error);
844 SetLastError((DWORD)Error);
845 return FALSE;
846 }
847
848 dwLength = sizeof(szRawImagePath);
849 Error = RegQueryValueExW(hKey,
850 L"ProfileImagePath",
851 NULL,
852 NULL,
853 (LPBYTE)szRawImagePath,
854 &dwLength);
855 if (Error != ERROR_SUCCESS)
856 {
857 DPRINT1("Error: %lu\n", Error);
858 RegCloseKey(hKey);
859 SetLastError((DWORD)Error);
860 return FALSE;
861 }
862
863 RegCloseKey(hKey);
864
865 DPRINT("RawImagePath: '%S'\n", szRawImagePath);
866
867 /* Expand it */
868 if (!ExpandEnvironmentStringsW(szRawImagePath,
869 szImagePath,
870 MAX_PATH))
871 {
872 DPRINT1 ("Error: %lu\n", GetLastError());
873 return FALSE;
874 }
875
876 DPRINT("ImagePath: '%S'\n", szImagePath);
877
878 dwLength = wcslen (szImagePath) + 1;
879 if (*lpcchSize < dwLength)
880 {
881 *lpcchSize = dwLength;
882 SetLastError(ERROR_INSUFFICIENT_BUFFER);
883 return FALSE;
884 }
885
886 *lpcchSize = dwLength;
887 wcscpy(lpProfileDir, szImagePath);
888
889 return TRUE;
890 }
891
892
893 static
894 BOOL
895 CheckForLoadedProfile(HANDLE hToken)
896 {
897 UNICODE_STRING SidString;
898 HKEY hKey;
899
900 DPRINT("CheckForLoadedProfile() called\n");
901
902 if (!GetUserSidStringFromToken(hToken,
903 &SidString))
904 {
905 DPRINT1("GetUserSidFromToken() failed\n");
906 return FALSE;
907 }
908
909 if (RegOpenKeyExW(HKEY_USERS,
910 SidString.Buffer,
911 0,
912 MAXIMUM_ALLOWED,
913 &hKey))
914 {
915 DPRINT("Profile not loaded\n");
916 RtlFreeUnicodeString(&SidString);
917 return FALSE;
918 }
919
920 RegCloseKey(hKey);
921
922 RtlFreeUnicodeString(&SidString);
923
924 DPRINT("Profile already loaded\n");
925
926 return TRUE;
927 }
928
929
930 BOOL
931 WINAPI
932 LoadUserProfileA(IN HANDLE hToken,
933 IN OUT LPPROFILEINFOA lpProfileInfo)
934 {
935 BOOL bResult = FALSE;
936 PROFILEINFOW ProfileInfoW = {0};
937 int len;
938
939 DPRINT("LoadUserProfileA() called\n");
940
941 /* Check profile info */
942 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOA)) ||
943 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
944 {
945 SetLastError(ERROR_INVALID_PARAMETER);
946 return FALSE;
947 }
948
949 /* Convert the structure to UNICODE... */
950 ProfileInfoW.dwSize = sizeof(PROFILEINFOW);
951 ProfileInfoW.dwFlags = lpProfileInfo->dwFlags;
952
953 if (lpProfileInfo->lpUserName)
954 {
955 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, NULL, 0);
956 ProfileInfoW.lpUserName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
957 if (!ProfileInfoW.lpUserName)
958 {
959 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
960 goto cleanup;
961 }
962 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, ProfileInfoW.lpUserName, len);
963 }
964
965 if (lpProfileInfo->lpProfilePath)
966 {
967 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, NULL, 0);
968 ProfileInfoW.lpProfilePath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
969 if (!ProfileInfoW.lpProfilePath)
970 {
971 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
972 goto cleanup;
973 }
974 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, ProfileInfoW.lpProfilePath, len);
975 }
976
977 if (lpProfileInfo->lpDefaultPath)
978 {
979 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, NULL, 0);
980 ProfileInfoW.lpDefaultPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
981 if (!ProfileInfoW.lpDefaultPath)
982 {
983 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
984 goto cleanup;
985 }
986 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, ProfileInfoW.lpDefaultPath, len);
987 }
988
989 if (lpProfileInfo->lpServerName)
990 {
991 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, NULL, 0);
992 ProfileInfoW.lpServerName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
993 if (!ProfileInfoW.lpServerName)
994 {
995 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
996 goto cleanup;
997 }
998 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, ProfileInfoW.lpServerName, len);
999 }
1000
1001 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && lpProfileInfo->lpPolicyPath)
1002 {
1003 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, NULL, 0);
1004 ProfileInfoW.lpPolicyPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1005 if (!ProfileInfoW.lpPolicyPath)
1006 {
1007 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1008 goto cleanup;
1009 }
1010 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, ProfileInfoW.lpPolicyPath, len);
1011 }
1012
1013 /* ... and call the UNICODE function */
1014 bResult = LoadUserProfileW(hToken, &ProfileInfoW);
1015
1016 /* Save the returned value */
1017 lpProfileInfo->hProfile = ProfileInfoW.hProfile;
1018
1019 cleanup:
1020 /* Memory cleanup */
1021 if (ProfileInfoW.lpUserName)
1022 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpUserName);
1023
1024 if (ProfileInfoW.lpProfilePath)
1025 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpProfilePath);
1026
1027 if (ProfileInfoW.lpDefaultPath)
1028 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpDefaultPath);
1029
1030 if (ProfileInfoW.lpServerName)
1031 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpServerName);
1032
1033 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && ProfileInfoW.lpPolicyPath)
1034 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpPolicyPath);
1035
1036 return bResult;
1037 }
1038
1039
1040 BOOL
1041 WINAPI
1042 LoadUserProfileW(IN HANDLE hToken,
1043 IN OUT LPPROFILEINFOW lpProfileInfo)
1044 {
1045 WCHAR szUserHivePath[MAX_PATH];
1046 LPWSTR UserName = NULL, Domain = NULL;
1047 DWORD UserNameLength = 0, DomainLength = 0;
1048 PTOKEN_USER UserSid = NULL;
1049 SID_NAME_USE AccountType;
1050 UNICODE_STRING SidString = { 0, 0, NULL };
1051 LONG Error;
1052 BOOL ret = FALSE;
1053 DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
1054
1055 DPRINT("LoadUserProfileW() called\n");
1056
1057 /* Check profile info */
1058 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOW)) ||
1059 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
1060 {
1061 SetLastError(ERROR_INVALID_PARAMETER);
1062 return FALSE;
1063 }
1064
1065 /* Don't load a profile twice */
1066 if (CheckForLoadedProfile(hToken))
1067 {
1068 DPRINT ("Profile already loaded\n");
1069 lpProfileInfo->hProfile = NULL;
1070 return TRUE;
1071 }
1072
1073 if (lpProfileInfo->lpProfilePath)
1074 {
1075 wcscpy(szUserHivePath, lpProfileInfo->lpProfilePath);
1076 }
1077 else
1078 {
1079 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
1080 if (!GetProfilesDirectoryW(szUserHivePath, &dwLength))
1081 {
1082 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
1083 return FALSE;
1084 }
1085 }
1086
1087 /* Create user hive name */
1088 wcscat(szUserHivePath, L"\\");
1089 wcscat(szUserHivePath, lpProfileInfo->lpUserName);
1090 wcscat(szUserHivePath, L"\\ntuser.dat");
1091 DPRINT("szUserHivePath: %S\n", szUserHivePath);
1092
1093 /* Create user profile directory if needed */
1094 if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES)
1095 {
1096 /* Get user sid */
1097 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) ||
1098 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1099 {
1100 DPRINT1 ("GetTokenInformation() failed\n");
1101 return FALSE;
1102 }
1103
1104 UserSid = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, dwLength);
1105 if (!UserSid)
1106 {
1107 DPRINT1("HeapAlloc() failed\n");
1108 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1109 goto cleanup;
1110 }
1111
1112 if (!GetTokenInformation(hToken, TokenUser, UserSid, dwLength, &dwLength))
1113 {
1114 DPRINT1("GetTokenInformation() failed\n");
1115 goto cleanup;
1116 }
1117
1118 /* Get user name */
1119 do
1120 {
1121 if (UserNameLength > 0)
1122 {
1123 HeapFree(GetProcessHeap(), 0, UserName);
1124 UserName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, UserNameLength * sizeof(WCHAR));
1125 if (!UserName)
1126 {
1127 DPRINT1("HeapAlloc() failed\n");
1128 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1129 goto cleanup;
1130 }
1131 }
1132 if (DomainLength > 0)
1133 {
1134 HeapFree(GetProcessHeap(), 0, Domain);
1135 Domain = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, DomainLength * sizeof(WCHAR));
1136 if (!Domain)
1137 {
1138 DPRINT1("HeapAlloc() failed\n");
1139 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1140 goto cleanup;
1141 }
1142 }
1143 ret = LookupAccountSidW(NULL,
1144 UserSid->User.Sid,
1145 UserName,
1146 &UserNameLength,
1147 Domain,
1148 &DomainLength,
1149 &AccountType);
1150 } while (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
1151
1152 if (!ret)
1153 {
1154 DPRINT1("LookupAccountSidW() failed\n");
1155 goto cleanup;
1156 }
1157
1158 /* Create profile */
1159 /* FIXME: ignore Domain? */
1160 DPRINT("UserName %S, Domain %S\n", UserName, Domain);
1161 ret = CreateUserProfileW(UserSid->User.Sid, UserName);
1162 if (!ret)
1163 {
1164 DPRINT1("CreateUserProfileW() failed\n");
1165 goto cleanup;
1166 }
1167 }
1168
1169 /* Get user SID string */
1170 ret = GetUserSidStringFromToken(hToken, &SidString);
1171 if (!ret)
1172 {
1173 DPRINT1("GetUserSidFromToken() failed\n");
1174 goto cleanup;
1175 }
1176 ret = FALSE;
1177
1178 /* Acquire restore privilege */
1179 if (!AcquireRemoveRestorePrivilege(TRUE))
1180 {
1181 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1182 goto cleanup;
1183 }
1184
1185 /* Load user registry hive */
1186 Error = RegLoadKeyW(HKEY_USERS,
1187 SidString.Buffer,
1188 szUserHivePath);
1189 AcquireRemoveRestorePrivilege(FALSE);
1190
1191 /* HACK: Do not fail if the profile has already been loaded! */
1192 if (Error == ERROR_SHARING_VIOLATION)
1193 Error = ERROR_SUCCESS;
1194
1195 if (Error != ERROR_SUCCESS)
1196 {
1197 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error);
1198 SetLastError((DWORD)Error);
1199 goto cleanup;
1200 }
1201
1202 /* Open future HKEY_CURRENT_USER */
1203 Error = RegOpenKeyExW(HKEY_USERS,
1204 SidString.Buffer,
1205 0,
1206 MAXIMUM_ALLOWED,
1207 (PHKEY)&lpProfileInfo->hProfile);
1208 if (Error != ERROR_SUCCESS)
1209 {
1210 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
1211 SetLastError((DWORD)Error);
1212 goto cleanup;
1213 }
1214
1215 ret = TRUE;
1216
1217 cleanup:
1218 HeapFree(GetProcessHeap(), 0, UserSid);
1219 HeapFree(GetProcessHeap(), 0, UserName);
1220 HeapFree(GetProcessHeap(), 0, Domain);
1221 RtlFreeUnicodeString(&SidString);
1222
1223 DPRINT("LoadUserProfileW() done\n");
1224 return ret;
1225 }
1226
1227
1228 BOOL
1229 WINAPI
1230 UnloadUserProfile(HANDLE hToken,
1231 HANDLE hProfile)
1232 {
1233 UNICODE_STRING SidString;
1234 LONG Error;
1235
1236 DPRINT("UnloadUserProfile() called\n");
1237
1238 if (hProfile == NULL)
1239 {
1240 DPRINT1("Invalid profile handle\n");
1241 SetLastError(ERROR_INVALID_PARAMETER);
1242 return FALSE;
1243 }
1244
1245 RegCloseKey(hProfile);
1246
1247 if (!GetUserSidStringFromToken(hToken,
1248 &SidString))
1249 {
1250 DPRINT1("GetUserSidFromToken() failed\n");
1251 return FALSE;
1252 }
1253
1254 DPRINT("SidString: '%wZ'\n", &SidString);
1255
1256 /* Acquire restore privilege */
1257 if (!AcquireRemoveRestorePrivilege(TRUE))
1258 {
1259 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1260 RtlFreeUnicodeString(&SidString);
1261 return FALSE;
1262 }
1263
1264 /* Unload the hive */
1265 Error = RegUnLoadKeyW(HKEY_USERS,
1266 SidString.Buffer);
1267
1268 /* Remove restore privilege */
1269 AcquireRemoveRestorePrivilege(FALSE);
1270
1271 if (Error != ERROR_SUCCESS)
1272 {
1273 DPRINT1("RegUnLoadKeyW() failed (Error %ld)\n", Error);
1274 RtlFreeUnicodeString(&SidString);
1275 SetLastError((DWORD)Error);
1276 return FALSE;
1277 }
1278
1279 RtlFreeUnicodeString(&SidString);
1280
1281 DPRINT("UnloadUserProfile() done\n");
1282
1283 return TRUE;
1284 }
1285
1286
1287 BOOL
1288 WINAPI
1289 DeleteProfileW(LPCWSTR lpSidString,
1290 LPCWSTR lpProfilePath,
1291 LPCWSTR lpComputerName)
1292 {
1293 DPRINT1("DeleteProfileW() not implemented!\n");
1294 return FALSE;
1295 }
1296
1297
1298 BOOL
1299 WINAPI
1300 DeleteProfileA(LPCSTR lpSidString,
1301 LPCSTR lpProfilePath,
1302 LPCSTR lpComputerName)
1303 {
1304 BOOL bResult;
1305 UNICODE_STRING SidString, ProfilePath, ComputerName;
1306
1307 DPRINT("DeleteProfileA() called\n");
1308
1309 /* Conversion to UNICODE */
1310 if (lpSidString)
1311 RtlCreateUnicodeStringFromAsciiz(&SidString,
1312 (LPSTR)lpSidString);
1313
1314 if (lpProfilePath)
1315 RtlCreateUnicodeStringFromAsciiz(&ProfilePath,
1316 (LPSTR)lpProfilePath);
1317
1318 if (lpComputerName)
1319 RtlCreateUnicodeStringFromAsciiz(&ComputerName,
1320 (LPSTR)lpComputerName);
1321
1322 /* Call the UNICODE function */
1323 bResult = DeleteProfileW(SidString.Buffer,
1324 ProfilePath.Buffer,
1325 ComputerName.Buffer);
1326
1327 /* Memory cleanup */
1328 if (lpSidString)
1329 RtlFreeUnicodeString(&SidString);
1330
1331 if (lpProfilePath)
1332 RtlFreeUnicodeString(&ProfilePath);
1333
1334 if (lpComputerName)
1335 RtlFreeUnicodeString(&ComputerName);
1336
1337 return bResult;
1338 }
1339
1340
1341 BOOL
1342 WINAPI
1343 GetProfileType(OUT PDWORD pdwFlags)
1344 {
1345 DPRINT1("GetProfileType() not implemented!\n");
1346 return FALSE;
1347 }
1348
1349 /* EOF */