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