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