3 * Copyright (C) 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS system libraries
23 * FILE: lib/userenv/profile.c
24 * PURPOSE: User profile code
25 * PROGRAMMER: Eric Kohl
34 /* FUNCTIONS ***************************************************************/
37 AppendSystemPostfix (LPWSTR lpName
,
40 WCHAR szSystemRoot
[MAX_PATH
];
44 /* Build profile name postfix */
45 if (!ExpandEnvironmentStringsW (L
"%SystemRoot%",
49 DPRINT1("Error: %lu\n", GetLastError());
53 _wcsupr (szSystemRoot
);
55 /* Get name postfix */
56 szSystemRoot
[2] = L
'.';
57 lpszPostfix
= &szSystemRoot
[2];
58 lpszPtr
= lpszPostfix
;
59 while (*lpszPtr
!= (WCHAR
)0)
61 if (*lpszPtr
== L
'\\')
66 if (wcslen(lpName
) + wcslen(lpszPostfix
) >= dwMaxLength
)
68 DPRINT1("Error: buffer overflow\n");
69 SetLastError(ERROR_BUFFER_OVERFLOW
);
73 wcscat(lpName
, lpszPostfix
);
80 CreateUserProfileA (PSID Sid
,
83 UNICODE_STRING UserName
;
87 Status
= RtlCreateUnicodeStringFromAsciiz (&UserName
,
89 if (!NT_SUCCESS(Status
))
91 SetLastError (RtlNtStatusToDosError (Status
));
95 bResult
= CreateUserProfileW (Sid
,
98 RtlFreeUnicodeString (&UserName
);
105 CreateUserProfileW (PSID Sid
,
108 WCHAR szRawProfilesPath
[MAX_PATH
];
109 WCHAR szProfilesPath
[MAX_PATH
];
110 WCHAR szUserProfilePath
[MAX_PATH
];
111 WCHAR szDefaultUserPath
[MAX_PATH
];
112 WCHAR szBuffer
[MAX_PATH
];
119 DPRINT("CreateUserProfileW() called\n");
121 Error
= RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
122 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
126 if (Error
!= ERROR_SUCCESS
)
128 DPRINT1("Error: %lu\n", Error
);
129 SetLastError((DWORD
)Error
);
133 /* Get profiles path */
134 dwLength
= MAX_PATH
* sizeof(WCHAR
);
135 Error
= RegQueryValueExW (hKey
,
136 L
"ProfilesDirectory",
139 (LPBYTE
)szRawProfilesPath
,
141 if (Error
!= ERROR_SUCCESS
)
143 DPRINT1("Error: %lu\n", Error
);
145 SetLastError((DWORD
)Error
);
150 if (!ExpandEnvironmentStringsW (szRawProfilesPath
,
154 DPRINT1("Error: %lu\n", GetLastError());
159 /* Get default user path */
160 dwLength
= MAX_PATH
* sizeof(WCHAR
);
161 Error
= RegQueryValueExW (hKey
,
162 L
"DefaultUserProfile",
167 if (Error
!= ERROR_SUCCESS
)
169 DPRINT1("Error: %lu\n", Error
);
171 SetLastError((DWORD
)Error
);
177 wcscpy (szUserProfilePath
, szProfilesPath
);
178 wcscat (szUserProfilePath
, L
"\\");
179 wcscat (szUserProfilePath
, lpUserName
);
180 if (!AppendSystemPostfix (szUserProfilePath
, MAX_PATH
))
182 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
183 LocalFree ((HLOCAL
)SidString
);
188 wcscpy (szDefaultUserPath
, szProfilesPath
);
189 wcscat (szDefaultUserPath
, L
"\\");
190 wcscat (szDefaultUserPath
, szBuffer
);
192 /* Create user profile directory */
193 if (!CreateDirectoryW (szUserProfilePath
, NULL
))
195 if (GetLastError () != ERROR_ALREADY_EXISTS
)
197 DPRINT1("Error: %lu\n", GetLastError());
202 /* Copy default user directory */
203 if (!CopyDirectory (szUserProfilePath
, szDefaultUserPath
))
205 DPRINT1("Error: %lu\n", GetLastError());
209 /* Add profile to profile list */
210 if (!ConvertSidToStringSidW (Sid
,
213 DPRINT1("Error: %lu\n", GetLastError());
218 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
219 wcscat (szBuffer
, SidString
);
221 /* Create user profile key */
222 Error
= RegCreateKeyExW (HKEY_LOCAL_MACHINE
,
226 REG_OPTION_NON_VOLATILE
,
231 if (Error
!= ERROR_SUCCESS
)
233 DPRINT1("Error: %lu\n", Error
);
234 LocalFree ((HLOCAL
)SidString
);
235 SetLastError((DWORD
)Error
);
239 /* Create non-expanded user profile path */
240 wcscpy (szBuffer
, szRawProfilesPath
);
241 wcscat (szBuffer
, L
"\\");
242 wcscat (szBuffer
, lpUserName
);
243 if (!AppendSystemPostfix (szBuffer
, MAX_PATH
))
245 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
246 LocalFree ((HLOCAL
)SidString
);
251 /* Set 'ProfileImagePath' value (non-expanded) */
252 Error
= RegSetValueExW (hKey
,
257 (wcslen (szBuffer
) + 1) * sizeof(WCHAR
));
258 if (Error
!= ERROR_SUCCESS
)
260 DPRINT1("Error: %lu\n", Error
);
261 LocalFree ((HLOCAL
)SidString
);
263 SetLastError((DWORD
)Error
);
267 /* Set 'Sid' value */
268 Error
= RegSetValueExW (hKey
,
274 if (Error
!= ERROR_SUCCESS
)
276 DPRINT1("Error: %lu\n", Error
);
277 LocalFree ((HLOCAL
)SidString
);
279 SetLastError((DWORD
)Error
);
285 /* Create user hive name */
286 wcscpy (szBuffer
, szUserProfilePath
);
287 wcscat (szBuffer
, L
"\\ntuser.dat");
289 /* Create new user hive */
290 Error
= RegLoadKeyW (HKEY_USERS
,
293 if (Error
!= ERROR_SUCCESS
)
295 DPRINT1("Error: %lu\n", Error
);
296 LocalFree ((HLOCAL
)SidString
);
297 SetLastError((DWORD
)Error
);
301 /* Initialize user hive */
302 if (!CreateUserHive (SidString
, szUserProfilePath
))
304 DPRINT1("Error: %lu\n", GetLastError());
305 LocalFree ((HLOCAL
)SidString
);
309 RegUnLoadKeyW (HKEY_USERS
,
312 LocalFree ((HLOCAL
)SidString
);
314 DPRINT("CreateUserProfileW() done\n");
321 GetAllUsersProfileDirectoryA (LPSTR lpProfileDir
,
327 lpBuffer
= GlobalAlloc (GMEM_FIXED
,
328 *lpcchSize
* sizeof(WCHAR
));
329 if (lpBuffer
== NULL
)
332 bResult
= GetAllUsersProfileDirectoryW (lpBuffer
,
336 WideCharToMultiByte (CP_ACP
,
346 GlobalFree (lpBuffer
);
353 GetAllUsersProfileDirectoryW (LPWSTR lpProfileDir
,
356 WCHAR szProfilePath
[MAX_PATH
];
357 WCHAR szBuffer
[MAX_PATH
];
362 Error
= RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
363 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
367 if (Error
!= ERROR_SUCCESS
)
369 DPRINT1("Error: %lu\n", Error
);
370 SetLastError((DWORD
)Error
);
374 /* Get profiles path */
375 dwLength
= sizeof(szBuffer
);
376 Error
= RegQueryValueExW (hKey
,
377 L
"ProfilesDirectory",
382 if (Error
!= ERROR_SUCCESS
)
384 DPRINT1("Error: %lu\n", Error
);
386 SetLastError((DWORD
)Error
);
391 if (!ExpandEnvironmentStringsW (szBuffer
,
395 DPRINT1("Error: %lu\n", GetLastError());
400 /* Get 'AllUsersProfile' name */
401 dwLength
= sizeof(szBuffer
);
402 Error
= RegQueryValueExW (hKey
,
408 if (Error
!= ERROR_SUCCESS
)
410 DPRINT1("Error: %lu\n", Error
);
412 SetLastError((DWORD
)Error
);
418 wcscat (szProfilePath
, L
"\\");
419 wcscat (szProfilePath
, szBuffer
);
421 dwLength
= wcslen (szProfilePath
) + 1;
422 if (lpProfileDir
!= NULL
)
424 if (*lpcchSize
< dwLength
)
426 *lpcchSize
= dwLength
;
427 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
431 wcscpy (lpProfileDir
, szProfilePath
);
434 *lpcchSize
= dwLength
;
441 GetDefaultUserProfileDirectoryA (LPSTR lpProfileDir
,
447 lpBuffer
= GlobalAlloc (GMEM_FIXED
,
448 *lpcchSize
* sizeof(WCHAR
));
449 if (lpBuffer
== NULL
)
452 bResult
= GetDefaultUserProfileDirectoryW (lpBuffer
,
456 WideCharToMultiByte (CP_ACP
,
466 GlobalFree (lpBuffer
);
473 GetDefaultUserProfileDirectoryW (LPWSTR lpProfileDir
,
476 WCHAR szProfilePath
[MAX_PATH
];
477 WCHAR szBuffer
[MAX_PATH
];
482 Error
= RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
483 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
487 if (Error
!= ERROR_SUCCESS
)
489 DPRINT1("Error: %lu\n", Error
);
490 SetLastError((DWORD
)Error
);
494 /* Get profiles path */
495 dwLength
= sizeof(szBuffer
);
496 Error
= RegQueryValueExW (hKey
,
497 L
"ProfilesDirectory",
502 if (Error
!= ERROR_SUCCESS
)
504 DPRINT1("Error: %lu\n", Error
);
506 SetLastError((DWORD
)Error
);
511 if (!ExpandEnvironmentStringsW (szBuffer
,
515 DPRINT1("Error: %lu\n", GetLastError());
520 /* Get 'DefaultUserProfile' name */
521 dwLength
= sizeof(szBuffer
);
522 Error
= RegQueryValueExW (hKey
,
523 L
"DefaultUserProfile",
528 if (Error
!= ERROR_SUCCESS
)
530 DPRINT1("Error: %lu\n", Error
);
532 SetLastError((DWORD
)Error
);
538 wcscat (szProfilePath
, L
"\\");
539 wcscat (szProfilePath
, szBuffer
);
541 dwLength
= wcslen (szProfilePath
) + 1;
542 if (lpProfileDir
!= NULL
)
544 if (*lpcchSize
< dwLength
)
546 *lpcchSize
= dwLength
;
547 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
551 wcscpy (lpProfileDir
, szProfilePath
);
554 *lpcchSize
= dwLength
;
561 GetProfilesDirectoryA (LPSTR lpProfileDir
,
567 lpBuffer
= GlobalAlloc (GMEM_FIXED
,
568 *lpcchSize
* sizeof(WCHAR
));
569 if (lpBuffer
== NULL
)
572 bResult
= GetProfilesDirectoryW (lpBuffer
,
576 WideCharToMultiByte (CP_ACP
,
586 GlobalFree (lpBuffer
);
593 GetProfilesDirectoryW (LPWSTR lpProfilesDir
,
596 WCHAR szProfilesPath
[MAX_PATH
];
597 WCHAR szBuffer
[MAX_PATH
];
602 Error
= RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
603 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
607 if (Error
!= ERROR_SUCCESS
)
609 DPRINT1("Error: %lu\n", Error
);
610 SetLastError((DWORD
)Error
);
614 /* Get profiles path */
615 dwLength
= sizeof(szBuffer
);
616 Error
= RegQueryValueExW (hKey
,
617 L
"ProfilesDirectory",
622 if (Error
!= ERROR_SUCCESS
)
624 DPRINT1("Error: %lu\n", Error
);
626 SetLastError((DWORD
)Error
);
633 if (!ExpandEnvironmentStringsW (szBuffer
,
637 DPRINT1("Error: %lu\n", GetLastError());
641 dwLength
= wcslen (szProfilesPath
) + 1;
642 if (lpProfilesDir
!= NULL
)
644 if (*lpcchSize
< dwLength
)
646 *lpcchSize
= dwLength
;
647 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
651 wcscpy (lpProfilesDir
, szProfilesPath
);
654 *lpcchSize
= dwLength
;
661 GetUserProfileDirectoryA (HANDLE hToken
,
668 lpBuffer
= GlobalAlloc (GMEM_FIXED
,
669 *lpcchSize
* sizeof(WCHAR
));
670 if (lpBuffer
== NULL
)
673 bResult
= GetUserProfileDirectoryW (hToken
,
678 WideCharToMultiByte (CP_ACP
,
688 GlobalFree (lpBuffer
);
695 GetUserProfileDirectoryW (HANDLE hToken
,
699 UNICODE_STRING SidString
;
700 WCHAR szKeyName
[MAX_PATH
];
701 WCHAR szRawImagePath
[MAX_PATH
];
702 WCHAR szImagePath
[MAX_PATH
];
707 if (!GetUserSidFromToken (hToken
,
710 DPRINT1 ("GetUserSidFromToken() failed\n");
714 DPRINT ("SidString: '%wZ'\n", &SidString
);
717 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
721 RtlFreeUnicodeString (&SidString
);
723 DPRINT ("KeyName: '%S'\n", szKeyName
);
725 Error
= RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
730 if (Error
!= ERROR_SUCCESS
)
732 DPRINT1 ("Error: %lu\n", Error
);
733 SetLastError((DWORD
)Error
);
737 dwLength
= sizeof(szRawImagePath
);
738 Error
= RegQueryValueExW (hKey
,
742 (LPBYTE
)szRawImagePath
,
744 if (Error
!= ERROR_SUCCESS
)
746 DPRINT1 ("Error: %lu\n", Error
);
748 SetLastError((DWORD
)Error
);
754 DPRINT ("RawImagePath: '%S'\n", szRawImagePath
);
757 if (!ExpandEnvironmentStringsW (szRawImagePath
,
761 DPRINT1 ("Error: %lu\n", GetLastError());
765 DPRINT ("ImagePath: '%S'\n", szImagePath
);
767 dwLength
= wcslen (szImagePath
) + 1;
768 if (*lpcchSize
< dwLength
)
770 DPRINT1 ("Buffer too small\n");
771 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
775 *lpcchSize
= dwLength
;
776 wcscpy (lpProfileDir
,
784 CheckForLoadedProfile (HANDLE hToken
)
786 UNICODE_STRING SidString
;
789 DPRINT ("CheckForLoadedProfile() called \n");
791 if (!GetUserSidFromToken (hToken
,
794 DPRINT1 ("GetUserSidFromToken() failed\n");
798 if (RegOpenKeyExW (HKEY_USERS
,
804 DPRINT ("Profile not loaded\n");
805 RtlFreeUnicodeString (&SidString
);
811 RtlFreeUnicodeString (&SidString
);
813 DPRINT ("Profile already loaded\n");
820 LoadUserProfileA (HANDLE hToken
,
821 LPPROFILEINFOA lpProfileInfo
)
823 DPRINT ("LoadUserProfileA() not implemented\n");
829 LoadUserProfileW (HANDLE hToken
,
830 LPPROFILEINFOW lpProfileInfo
)
832 WCHAR szUserHivePath
[MAX_PATH
];
833 UNICODE_STRING SidString
;
835 DWORD dwLength
= sizeof(szUserHivePath
) / sizeof(szUserHivePath
[0]);
837 DPRINT ("LoadUserProfileW() called\n");
839 /* Check profile info */
840 if (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOW
) ||
841 lpProfileInfo
->lpUserName
== NULL
||
842 lpProfileInfo
->lpUserName
[0] == 0)
844 SetLastError (ERROR_INVALID_PARAMETER
);
848 /* Don't load a profile twice */
849 if (CheckForLoadedProfile (hToken
))
851 DPRINT ("Profile already loaded\n");
852 lpProfileInfo
->hProfile
= NULL
;
856 if (!GetProfilesDirectoryW (szUserHivePath
,
859 DPRINT1("GetProfilesDirectoryW() failed\n", GetLastError());
863 wcscat (szUserHivePath
, L
"\\");
864 wcscat (szUserHivePath
, lpProfileInfo
->lpUserName
);
865 if (!AppendSystemPostfix (szUserHivePath
, MAX_PATH
))
867 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
871 /* Create user hive name */
872 wcscat (szUserHivePath
, L
"\\ntuser.dat");
874 DPRINT ("szUserHivePath: %S\n", szUserHivePath
);
876 if (!GetUserSidFromToken (hToken
,
879 DPRINT1 ("GetUserSidFromToken() failed\n");
883 DPRINT ("SidString: '%wZ'\n", &SidString
);
885 Error
= RegLoadKeyW (HKEY_USERS
,
888 if (Error
!= ERROR_SUCCESS
)
890 DPRINT1 ("RegLoadKeyW() failed (Error %ld)\n", Error
);
891 RtlFreeUnicodeString (&SidString
);
892 SetLastError((DWORD
)Error
);
896 Error
= RegOpenKeyExW (HKEY_USERS
,
900 (PHKEY
)&lpProfileInfo
->hProfile
);
901 if (Error
!= ERROR_SUCCESS
)
903 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", Error
);
904 RtlFreeUnicodeString (&SidString
);
905 SetLastError((DWORD
)Error
);
909 RtlFreeUnicodeString (&SidString
);
911 DPRINT ("LoadUserProfileW() done\n");
918 UnloadUserProfile (HANDLE hToken
,
921 UNICODE_STRING SidString
;
924 DPRINT ("UnloadUserProfile() called\n");
926 if (hProfile
== NULL
)
928 DPRINT1 ("Invalide profile handle\n");
929 SetLastError (ERROR_INVALID_PARAMETER
);
933 RegCloseKey (hProfile
);
935 if (!GetUserSidFromToken (hToken
,
938 DPRINT1 ("GetUserSidFromToken() failed\n");
942 DPRINT ("SidString: '%wZ'\n", &SidString
);
944 Error
= RegUnLoadKeyW (HKEY_USERS
,
946 if (Error
!= ERROR_SUCCESS
)
948 DPRINT1 ("RegUnLoadKeyW() failed (Error %ld)\n", Error
);
949 RtlFreeUnicodeString (&SidString
);
950 SetLastError((DWORD
)Error
);
954 RtlFreeUnicodeString (&SidString
);
956 DPRINT ("UnloadUserProfile() done\n");