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.
19 /* $Id: profile.c,v 1.14 2004/10/03 09:27:22 ekohl Exp $
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
31 /* FUNCTIONS ***************************************************************/
34 AppendSystemPostfix (LPWSTR lpName
,
37 WCHAR szSystemRoot
[MAX_PATH
];
38 WCHAR szDrivePostfix
[3];
41 DWORD dwPostfixLength
;
43 /* Build profile name postfix */
44 if (!ExpandEnvironmentStringsW (L
"%SystemRoot%",
48 DPRINT1("Error: %lu\n", GetLastError());
52 _wcsupr (szSystemRoot
);
54 /* Get name postfix */
55 szSystemRoot
[2] = L
'.';
56 lpszPostfix
= &szSystemRoot
[2];
57 lpszPtr
= lpszPostfix
;
58 while (*lpszPtr
!= (WCHAR
)0)
60 if (*lpszPtr
== L
'\\')
65 dwPostfixLength
= wcslen (lpszPostfix
);
66 if (szSystemRoot
[0] != L
'C')
69 szDrivePostfix
[0] = L
'_';
70 szDrivePostfix
[1] = szSystemRoot
[0];
71 szDrivePostfix
[2] = (WCHAR
)0;
74 if (wcslen (lpName
) + dwPostfixLength
>= dwMaxLength
)
76 DPRINT1("Error: buffer overflow\n");
80 wcscat (lpName
, lpszPostfix
);
81 if (szSystemRoot
[0] != L
'C')
83 wcscat (lpName
, szDrivePostfix
);
91 CreateUserProfileA (PSID Sid
,
94 UNICODE_STRING UserName
;
98 Status
= RtlCreateUnicodeStringFromAsciiz (&UserName
,
100 if (!NT_SUCCESS(Status
))
102 SetLastError (RtlNtStatusToDosError (Status
));
106 bResult
= CreateUserProfileW (Sid
,
109 RtlFreeUnicodeString (&UserName
);
116 CreateUserProfileW (PSID Sid
,
119 WCHAR szRawProfilesPath
[MAX_PATH
];
120 WCHAR szProfilesPath
[MAX_PATH
];
121 WCHAR szUserProfilePath
[MAX_PATH
];
122 WCHAR szDefaultUserPath
[MAX_PATH
];
123 WCHAR szBuffer
[MAX_PATH
];
124 UNICODE_STRING SidString
;
130 DPRINT("CreateUserProfileW() called\n");
132 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
133 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
138 DPRINT1("Error: %lu\n", GetLastError());
142 /* Get profiles path */
143 dwLength
= MAX_PATH
* sizeof(WCHAR
);
144 if (RegQueryValueExW (hKey
,
145 L
"ProfilesDirectory",
148 (LPBYTE
)szRawProfilesPath
,
151 DPRINT1("Error: %lu\n", GetLastError());
157 if (!ExpandEnvironmentStringsW (szRawProfilesPath
,
161 DPRINT1("Error: %lu\n", GetLastError());
166 /* Get default user path */
167 dwLength
= MAX_PATH
* sizeof(WCHAR
);
168 if (RegQueryValueExW (hKey
,
169 L
"DefaultUserProfile",
175 DPRINT1("Error: %lu\n", GetLastError());
182 wcscpy (szUserProfilePath
, szProfilesPath
);
183 wcscat (szUserProfilePath
, L
"\\");
184 wcscat (szUserProfilePath
, lpUserName
);
185 if (!AppendSystemPostfix (szUserProfilePath
, MAX_PATH
))
187 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
188 RtlFreeUnicodeString (&SidString
);
193 wcscpy (szDefaultUserPath
, szProfilesPath
);
194 wcscat (szDefaultUserPath
, L
"\\");
195 wcscat (szDefaultUserPath
, szBuffer
);
197 /* Create user profile directory */
198 if (!CreateDirectoryW (szUserProfilePath
, NULL
))
200 if (GetLastError () != ERROR_ALREADY_EXISTS
)
202 DPRINT1("Error: %lu\n", GetLastError());
207 /* Copy default user directory */
208 if (!CopyDirectory (szUserProfilePath
, szDefaultUserPath
))
210 DPRINT1("Error: %lu\n", GetLastError());
214 /* Add profile to profile list */
215 Status
= RtlConvertSidToUnicodeString (&SidString
, Sid
, TRUE
);
216 if (!NT_SUCCESS(Status
))
218 DPRINT1("Status: %lx\n", Status
);
223 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
224 wcscat (szBuffer
, SidString
.Buffer
);
226 /* Create user profile key */
227 if (RegCreateKeyExW (HKEY_LOCAL_MACHINE
,
231 REG_OPTION_NON_VOLATILE
,
237 DPRINT1("Error: %lu\n", GetLastError());
238 RtlFreeUnicodeString (&SidString
);
242 /* Create non-expanded user profile path */
243 wcscpy (szBuffer
, szRawProfilesPath
);
244 wcscat (szBuffer
, L
"\\");
245 wcscat (szBuffer
, lpUserName
);
246 if (!AppendSystemPostfix (szBuffer
, MAX_PATH
))
248 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
249 RtlFreeUnicodeString (&SidString
);
254 /* Set 'ProfileImagePath' value (non-expanded) */
255 if (RegSetValueExW (hKey
,
260 (wcslen (szBuffer
) + 1) * sizeof(WCHAR
)))
262 DPRINT1("Error: %lu\n", GetLastError());
263 RtlFreeUnicodeString (&SidString
);
268 /* Set 'Sid' value */
269 if (RegSetValueExW (hKey
,
276 DPRINT1("Error: %lu\n", GetLastError());
277 RtlFreeUnicodeString (&SidString
);
284 /* Create user hive name */
285 wcscpy (szBuffer
, szUserProfilePath
);
286 wcscat (szBuffer
, L
"\\ntuser.dat");
288 /* Create new user hive */
289 if (RegLoadKeyW (HKEY_USERS
,
293 DPRINT1("Error: %lu\n", GetLastError());
294 RtlFreeUnicodeString (&SidString
);
298 /* Initialize user hive */
299 if (!CreateUserHive (SidString
.Buffer
, szUserProfilePath
))
301 DPRINT1("Error: %lu\n", GetLastError());
302 RtlFreeUnicodeString (&SidString
);
306 RegUnLoadKeyW (HKEY_USERS
,
309 RtlFreeUnicodeString (&SidString
);
311 DPRINT("CreateUserProfileW() done\n");
318 GetAllUsersProfileDirectoryA (LPSTR lpProfileDir
,
324 lpBuffer
= GlobalAlloc (GMEM_FIXED
,
325 *lpcchSize
* sizeof(WCHAR
));
326 if (lpBuffer
== NULL
)
329 bResult
= GetAllUsersProfileDirectoryW (lpBuffer
,
333 WideCharToMultiByte (CP_ACP
,
343 GlobalFree (lpBuffer
);
350 GetAllUsersProfileDirectoryW (LPWSTR lpProfileDir
,
353 WCHAR szProfilePath
[MAX_PATH
];
354 WCHAR szBuffer
[MAX_PATH
];
358 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
359 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
364 DPRINT1("Error: %lu\n", GetLastError());
368 /* Get profiles path */
369 dwLength
= MAX_PATH
* sizeof(WCHAR
);
370 if (RegQueryValueExW (hKey
,
371 L
"ProfilesDirectory",
377 DPRINT1("Error: %lu\n", GetLastError());
383 if (!ExpandEnvironmentStringsW (szBuffer
,
387 DPRINT1("Error: %lu\n", GetLastError());
392 /* Get 'AllUsersProfile' name */
393 dwLength
= MAX_PATH
* sizeof(WCHAR
);
394 if (RegQueryValueExW (hKey
,
401 DPRINT1("Error: %lu\n", GetLastError());
408 wcscat (szProfilePath
, L
"\\");
409 wcscat (szProfilePath
, szBuffer
);
411 dwLength
= wcslen (szProfilePath
);
412 if (lpProfileDir
!= NULL
)
414 if (*lpcchSize
< dwLength
)
416 *lpcchSize
= dwLength
;
417 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
421 wcscpy (lpProfileDir
, szProfilePath
);
424 *lpcchSize
= dwLength
;
431 GetDefaultUserProfileDirectoryA (LPSTR lpProfileDir
,
437 lpBuffer
= GlobalAlloc (GMEM_FIXED
,
438 *lpcchSize
* sizeof(WCHAR
));
439 if (lpBuffer
== NULL
)
442 bResult
= GetDefaultUserProfileDirectoryW (lpBuffer
,
446 WideCharToMultiByte (CP_ACP
,
456 GlobalFree (lpBuffer
);
463 GetDefaultUserProfileDirectoryW (LPWSTR lpProfileDir
,
466 WCHAR szProfilePath
[MAX_PATH
];
467 WCHAR szBuffer
[MAX_PATH
];
471 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
472 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
477 DPRINT1("Error: %lu\n", GetLastError());
481 /* Get profiles path */
482 dwLength
= MAX_PATH
* sizeof(WCHAR
);
483 if (RegQueryValueExW (hKey
,
484 L
"ProfilesDirectory",
490 DPRINT1("Error: %lu\n", GetLastError());
496 if (!ExpandEnvironmentStringsW (szBuffer
,
500 DPRINT1("Error: %lu\n", GetLastError());
505 /* Get 'DefaultUserProfile' name */
506 dwLength
= MAX_PATH
* sizeof(WCHAR
);
507 if (RegQueryValueExW (hKey
,
508 L
"DefaultUserProfile",
514 DPRINT1("Error: %lu\n", GetLastError());
521 wcscat (szProfilePath
, L
"\\");
522 wcscat (szProfilePath
, szBuffer
);
524 dwLength
= wcslen (szProfilePath
);
525 if (lpProfileDir
!= NULL
)
527 if (*lpcchSize
< dwLength
)
529 *lpcchSize
= dwLength
;
530 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
534 wcscpy (lpProfileDir
, szProfilePath
);
537 *lpcchSize
= dwLength
;
544 GetProfilesDirectoryA (LPSTR lpProfileDir
,
550 lpBuffer
= GlobalAlloc (GMEM_FIXED
,
551 *lpcchSize
* sizeof(WCHAR
));
552 if (lpBuffer
== NULL
)
555 bResult
= GetProfilesDirectoryW (lpBuffer
,
559 WideCharToMultiByte (CP_ACP
,
569 GlobalFree (lpBuffer
);
576 GetProfilesDirectoryW (LPWSTR lpProfilesDir
,
579 WCHAR szProfilesPath
[MAX_PATH
];
580 WCHAR szBuffer
[MAX_PATH
];
584 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
585 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
590 DPRINT1("Error: %lu\n", GetLastError());
594 /* Get profiles path */
595 dwLength
= MAX_PATH
* sizeof(WCHAR
);
596 if (RegQueryValueExW (hKey
,
597 L
"ProfilesDirectory",
603 DPRINT1("Error: %lu\n", GetLastError());
611 if (!ExpandEnvironmentStringsW (szBuffer
,
615 DPRINT1("Error: %lu\n", GetLastError());
619 dwLength
= wcslen (szProfilesPath
);
620 if (lpProfilesDir
!= NULL
)
622 if (*lpcchSize
< dwLength
)
624 *lpcchSize
= dwLength
;
625 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
629 wcscpy (lpProfilesDir
, szProfilesPath
);
632 *lpcchSize
= dwLength
;
639 GetUserProfileDirectoryA (HANDLE hToken
,
646 lpBuffer
= GlobalAlloc (GMEM_FIXED
,
647 *lpcchSize
* sizeof(WCHAR
));
648 if (lpBuffer
== NULL
)
651 bResult
= GetUserProfileDirectoryW (hToken
,
656 WideCharToMultiByte (CP_ACP
,
666 GlobalFree (lpBuffer
);
673 GetUserProfileDirectoryW (HANDLE hToken
,
677 UNICODE_STRING SidString
;
678 WCHAR szKeyName
[MAX_PATH
];
679 WCHAR szRawImagePath
[MAX_PATH
];
680 WCHAR szImagePath
[MAX_PATH
];
684 if (!GetUserSidFromToken (hToken
,
687 DPRINT1 ("GetUserSidFromToken() failed\n");
691 DPRINT ("SidString: '%wZ'\n", &SidString
);
694 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
698 RtlFreeUnicodeString (&SidString
);
700 DPRINT ("KeyName: '%S'\n", szKeyName
);
702 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE
,
708 DPRINT1 ("Error: %lu\n", GetLastError());
712 dwLength
= MAX_PATH
* sizeof(WCHAR
);
713 if (RegQueryValueExW (hKey
,
717 (LPBYTE
)szRawImagePath
,
720 DPRINT1 ("Error: %lu\n", GetLastError());
727 DPRINT ("RawImagePath: '%S'\n", szRawImagePath
);
730 if (!ExpandEnvironmentStringsW (szRawImagePath
,
734 DPRINT1 ("Error: %lu\n", GetLastError());
738 DPRINT ("ImagePath: '%S'\n", szImagePath
);
740 dwLength
= wcslen (szImagePath
);
741 if (dwLength
> *lpcchSize
)
743 DPRINT1 ("Buffer too small\n");
744 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
748 *lpcchSize
= dwLength
;
749 wcscpy (lpProfileDir
,
757 CheckForLoadedProfile (HANDLE hToken
)
759 UNICODE_STRING SidString
;
762 DPRINT ("CheckForLoadedProfile() called \n");
764 if (!GetUserSidFromToken (hToken
,
767 DPRINT1 ("GetUserSidFromToken() failed\n");
771 if (RegOpenKeyExW (HKEY_USERS
,
777 DPRINT ("Profile not loaded\n");
778 RtlFreeUnicodeString (&SidString
);
784 RtlFreeUnicodeString (&SidString
);
786 DPRINT ("Profile already loaded\n");
793 LoadUserProfileA (HANDLE hToken
,
794 LPPROFILEINFOA lpProfileInfo
)
796 DPRINT ("LoadUserProfileA() not implemented\n");
802 LoadUserProfileW (HANDLE hToken
,
803 LPPROFILEINFOW lpProfileInfo
)
805 WCHAR szUserHivePath
[MAX_PATH
];
806 UNICODE_STRING SidString
;
809 DPRINT ("LoadUserProfileW() called\n");
811 /* Check profile info */
812 if (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOW
) ||
813 lpProfileInfo
->lpUserName
== NULL
||
814 lpProfileInfo
->lpUserName
[0] == 0)
816 SetLastError (ERROR_INVALID_PARAMETER
);
820 /* Don't load a profile twice */
821 if (CheckForLoadedProfile (hToken
))
823 DPRINT ("Profile already loaded\n");
824 lpProfileInfo
->hProfile
= NULL
;
828 if (!GetProfilesDirectoryW (szUserHivePath
,
831 DPRINT1("GetProfilesDirectoryW() failed\n", GetLastError());
835 wcscat (szUserHivePath
, L
"\\");
836 wcscat (szUserHivePath
, lpProfileInfo
->lpUserName
);
837 if (!AppendSystemPostfix (szUserHivePath
, MAX_PATH
))
839 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
843 /* Create user hive name */
844 wcscat (szUserHivePath
, L
"\\ntuser.dat");
846 DPRINT ("szUserHivePath: %S\n", szUserHivePath
);
848 if (!GetUserSidFromToken (hToken
,
851 DPRINT1 ("GetUserSidFromToken() failed\n");
855 DPRINT ("SidString: '%wZ'\n", &SidString
);
857 if (RegLoadKeyW (HKEY_USERS
,
861 DPRINT1 ("RegLoadKeyW() failed (Error %ld)\n", GetLastError());
862 RtlFreeUnicodeString (&SidString
);
866 if (RegOpenKeyExW (HKEY_USERS
,
870 (PHKEY
)&lpProfileInfo
->hProfile
))
872 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", GetLastError());
873 RtlFreeUnicodeString (&SidString
);
877 RtlFreeUnicodeString (&SidString
);
879 DPRINT ("LoadUserProfileW() done\n");
886 UnloadUserProfile (HANDLE hToken
,
889 UNICODE_STRING SidString
;
891 DPRINT ("UnloadUserProfile() called\n");
893 if (hProfile
== NULL
)
895 DPRINT1 ("Invalide profile handle\n");
896 SetLastError (ERROR_INVALID_PARAMETER
);
900 RegCloseKey (hProfile
);
902 if (!GetUserSidFromToken (hToken
,
905 DPRINT1 ("GetUserSidFromToken() failed\n");
909 DPRINT ("SidString: '%wZ'\n", &SidString
);
911 if (RegUnLoadKeyW (HKEY_USERS
,
914 DPRINT1 ("RegUnLoadKeyW() failed (Error %ld)\n", GetLastError());
915 RtlFreeUnicodeString (&SidString
);
919 RtlFreeUnicodeString (&SidString
);
921 DPRINT ("UnloadUserProfile() done\n");