2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/userenv/profile.c
5 * PURPOSE: User profile code
6 * PROGRAMMERS: Eric Kohl
17 /* FUNCTIONS ***************************************************************/
20 AppendSystemPostfix(LPWSTR lpName
,
23 WCHAR szSystemRoot
[MAX_PATH
];
27 /* Build profile name postfix */
28 if (!ExpandEnvironmentStringsW(L
"%SystemRoot%",
30 ARRAYSIZE(szSystemRoot
)))
32 DPRINT1("Error: %lu\n", GetLastError());
36 _wcsupr(szSystemRoot
);
38 /* Get name postfix */
39 szSystemRoot
[2] = L
'.';
40 lpszPostfix
= &szSystemRoot
[2];
41 lpszPtr
= lpszPostfix
;
42 while (*lpszPtr
!= (WCHAR
)0)
44 if (*lpszPtr
== L
'\\')
49 if (wcslen(lpName
) + wcslen(lpszPostfix
) + 1 >= dwMaxLength
)
51 DPRINT1("Error: buffer overflow\n");
52 SetLastError(ERROR_BUFFER_OVERFLOW
);
56 wcscat(lpName
, lpszPostfix
);
64 AcquireRemoveRestorePrivilege(IN BOOL bAcquire
)
68 TOKEN_PRIVILEGES TokenPriv
;
70 DPRINT("AcquireRemoveRestorePrivilege(%d)\n", bAcquire
);
72 if (OpenProcessToken(GetCurrentProcess(),
73 TOKEN_ADJUST_PRIVILEGES
,
76 TokenPriv
.PrivilegeCount
= 1;
77 TokenPriv
.Privileges
[0].Attributes
= (bAcquire
? SE_PRIVILEGE_ENABLED
: 0);
79 if (LookupPrivilegeValue(NULL
, SE_RESTORE_NAME
, &TokenPriv
.Privileges
[0].Luid
))
81 bRet
= AdjustTokenPrivileges(Token
, FALSE
, &TokenPriv
, 0, NULL
, NULL
);
85 DPRINT1("AdjustTokenPrivileges() failed with error %lu\n", GetLastError());
87 else if (GetLastError() == ERROR_NOT_ALL_ASSIGNED
)
89 DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
95 DPRINT1("LookupPrivilegeValue() failed with error %lu\n", GetLastError());
102 DPRINT1("OpenProcessToken() failed with error %lu\n", GetLastError());
111 CheckForLoadedProfile(HANDLE hToken
)
113 UNICODE_STRING SidString
;
116 DPRINT("CheckForLoadedProfile() called\n");
118 /* Get the user SID string */
119 if (!GetUserSidStringFromToken(hToken
, &SidString
))
121 DPRINT1("GetUserSidStringFromToken() failed\n");
125 if (RegOpenKeyExW(HKEY_USERS
,
131 DPRINT("Profile not loaded\n");
132 RtlFreeUnicodeString(&SidString
);
138 RtlFreeUnicodeString(&SidString
);
140 DPRINT("Profile already loaded\n");
146 /* PUBLIC FUNCTIONS ********************************************************/
153 WCHAR szKeyName
[MAX_PATH
];
154 WCHAR szRawProfilePath
[MAX_PATH
];
155 WCHAR szProfilePath
[MAX_PATH
];
156 WCHAR szDefaultProfilePath
[MAX_PATH
];
157 UNICODE_STRING SidString
= {0, 0, NULL
};
158 HANDLE hToken
= NULL
;
159 PSID pUserSid
= NULL
;
160 HKEY hProfileKey
= NULL
;
162 BOOL bResult
= FALSE
;
166 DPRINT1("CopySystemProfile()\n");
168 if (!OpenProcessToken(GetCurrentProcess(),
169 TOKEN_QUERY
| TOKEN_IMPERSONATE
,
172 DPRINT1("Failed to open the process token (Error %lu)\n", GetLastError());
176 pUserSid
= GetUserSid(hToken
);
177 if (pUserSid
== NULL
)
179 DPRINT1("Failed to get the users SID (Error %lu)\n", GetLastError());
183 /* Get the user SID string */
184 if (!GetUserSidStringFromToken(hToken
, &SidString
))
186 DPRINT1("GetUserSidStringFromToken() failed\n");
190 StringCbCopyW(szKeyName
, sizeof(szKeyName
),
191 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
192 StringCbCatW(szKeyName
, sizeof(szKeyName
), SidString
.Buffer
);
194 RtlFreeUnicodeString(&SidString
);
196 dwError
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
203 if (dwError
!= ERROR_SUCCESS
)
205 DPRINT1("Failed to create the profile key for the %s profile (Error %lu)\n",
206 SidString
.Buffer
, dwError
);
210 dwError
= RegSetValueExW(hProfileKey
,
215 RtlLengthSid(pUserSid
));
216 if (dwError
!= ERROR_SUCCESS
)
218 DPRINT1("Failed to set the SID value (Error %lu)\n", dwError
);
222 wcscpy(szRawProfilePath
,
223 L
"%systemroot%\\system32\\config\\systemprofile");
225 dwError
= RegSetValueExW(hProfileKey
,
229 (PBYTE
)szRawProfilePath
,
230 (wcslen(szRawProfilePath
) + 1) * sizeof(WCHAR
));
231 if (dwError
!= ERROR_SUCCESS
)
233 DPRINT1("Failed to set the ProfileImagePath value (Error %lu)\n", dwError
);
237 /* Expand the raw profile path */
238 if (!ExpandEnvironmentStringsW(szRawProfilePath
,
240 ARRAYSIZE(szProfilePath
)))
242 DPRINT1("Failled to expand the raw profile path (Error %lu)\n", GetLastError());
246 /* Create the profile directory if it does not exist yet */
248 if (!CreateDirectoryW(szProfilePath
, NULL
))
250 if (GetLastError() != ERROR_ALREADY_EXISTS
)
252 DPRINT1("Failed to create the profile directory (Error %lu)\n", GetLastError());
257 /* Get the path of the default profile */
258 cchSize
= ARRAYSIZE(szDefaultProfilePath
);
259 if (!GetDefaultUserProfileDirectoryW(szDefaultProfilePath
, &cchSize
))
261 DPRINT1("Failed to create the default profile path (Error %lu)\n", GetLastError());
265 /* Copy the default profile into the new profile directory */
267 if (!CopyDirectory(szProfilePath
, szDefaultProfilePath
))
269 DPRINT1("Failed to copy the default profile directory (Error %lu)\n", GetLastError());
276 if (hProfileKey
!= NULL
)
277 RegCloseKey(hProfileKey
);
279 RtlFreeUnicodeString(&SidString
);
281 if (pUserSid
!= NULL
)
295 _In_ LPCSTR lpUserName
)
297 LPWSTR pUserNameW
= NULL
;
301 DPRINT("CreateUserProfileA(%p %s)\n", pSid
, lpUserName
);
303 /* Convert lpUserName to Unicode */
304 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, NULL
, 0);
305 pUserNameW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
306 if (pUserNameW
== NULL
)
308 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
311 MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, pUserNameW
, nLength
);
313 /* Call the Ex function */
314 bResult
= CreateUserProfileExW(pSid
,
321 HeapFree(GetProcessHeap(), 0, pUserNameW
);
331 _In_ LPCWSTR lpUserName
)
333 DPRINT("CreateUserProfileW(%p %S)\n", pSid
, lpUserName
);
335 /* Call the Ex function */
336 return CreateUserProfileExW(pSid
,
347 CreateUserProfileExA(
349 _In_ LPCSTR lpUserName
,
350 _In_opt_ LPCSTR lpUserHive
,
351 _Out_opt_ LPSTR lpProfileDir
,
352 _In_ DWORD dwDirSize
,
355 LPWSTR pUserNameW
= NULL
;
356 LPWSTR pUserHiveW
= NULL
;
357 LPWSTR pProfileDirW
= NULL
;
359 BOOL bResult
= FALSE
;
361 DPRINT("CreateUserProfileExA(%p %s %s %p %lu %d)\n",
362 pSid
, lpUserName
, lpUserHive
, lpProfileDir
, dwDirSize
, bWin9xUpg
);
364 /* Check the parameters */
365 if (lpProfileDir
!= NULL
&& dwDirSize
== 0)
367 SetLastError(ERROR_INVALID_PARAMETER
);
371 /* Convert lpUserName to Unicode */
372 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, NULL
, 0);
373 pUserNameW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
374 if (pUserNameW
== NULL
)
376 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
379 MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, pUserNameW
, nLength
);
381 /* Convert lpUserHive to Unicode */
382 if (lpUserHive
!= NULL
)
384 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserHive
, -1, NULL
, 0);
385 pUserHiveW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
386 if (pUserHiveW
== NULL
)
388 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
391 MultiByteToWideChar(CP_ACP
, 0, lpUserHive
, -1, pUserHiveW
, nLength
);
394 /* Allocate a Unicode buffer for lpProfileDir */
395 if (lpProfileDir
!= NULL
)
397 pProfileDirW
= HeapAlloc(GetProcessHeap(), 0, dwDirSize
* sizeof(WCHAR
));
398 if (pProfileDirW
== NULL
)
400 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
405 /* Call the Unicode function */
406 bResult
= CreateUserProfileExW(pSid
,
413 /* Convert the profile path to ANSI */
414 if (bResult
&& lpProfileDir
!= NULL
)
416 WideCharToMultiByte(CP_ACP
, 0, pProfileDirW
, -1, lpProfileDir
, dwDirSize
, NULL
, NULL
);
420 /* Free the buffers */
421 if (pProfileDirW
!= NULL
)
422 HeapFree(GetProcessHeap(), 0, pProfileDirW
);
424 if (pUserHiveW
!= NULL
)
425 HeapFree(GetProcessHeap(), 0, pUserHiveW
);
427 if (pUserNameW
!= NULL
)
428 HeapFree(GetProcessHeap(), 0, pUserNameW
);
436 CreateUserProfileExW(
438 _In_ LPCWSTR lpUserName
,
439 _In_opt_ LPCWSTR lpUserHive
,
440 _Out_opt_ LPWSTR lpProfileDir
,
441 _In_ DWORD dwDirSize
,
444 WCHAR szRawProfilesPath
[MAX_PATH
];
445 WCHAR szProfilesPath
[MAX_PATH
];
446 WCHAR szUserProfilePath
[MAX_PATH
];
447 WCHAR szDefaultUserPath
[MAX_PATH
];
448 WCHAR szUserProfileName
[MAX_PATH
];
449 WCHAR szBuffer
[MAX_PATH
];
451 DWORD dwType
, dwLength
;
458 DPRINT("CreateUserProfileExW(%p %S %S %p %lu %d)\n",
459 pSid
, lpUserName
, lpUserHive
, lpProfileDir
, dwDirSize
, bWin9xUpg
);
461 /* Parameters validation */
462 if (!pSid
|| !lpUserName
)
464 SetLastError(ERROR_INVALID_PARAMETER
);
470 * - Add support for lpUserHive.
471 * - bWin9xUpg is obsolete. Don't waste your time implementing this.
474 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
475 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
479 if (Error
!= ERROR_SUCCESS
)
481 DPRINT1("Error: %lu\n", Error
);
482 SetLastError((DWORD
)Error
);
486 /* Get profiles path */
487 dwLength
= sizeof(szRawProfilesPath
);
488 Error
= RegQueryValueExW(hKey
,
489 L
"ProfilesDirectory",
492 (LPBYTE
)szRawProfilesPath
,
494 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
496 DPRINT1("Error: %lu\n", Error
);
498 SetLastError((DWORD
)Error
);
503 if (!ExpandEnvironmentStringsW(szRawProfilesPath
,
505 ARRAYSIZE(szProfilesPath
)))
507 DPRINT1("Error: %lu\n", GetLastError());
512 /* Create the profiles directory if it does not exist yet */
514 if (!CreateDirectoryW(szProfilesPath
, NULL
))
516 if (GetLastError() != ERROR_ALREADY_EXISTS
)
518 DPRINT1("Error: %lu\n", GetLastError());
523 /* Get default user path */
524 dwLength
= sizeof(szBuffer
);
525 Error
= RegQueryValueExW(hKey
,
526 L
"DefaultUserProfile",
531 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
533 DPRINT1("Error: %lu\n", Error
);
535 SetLastError((DWORD
)Error
);
541 StringCbCopyW(szUserProfileName
, sizeof(szUserProfileName
), lpUserName
);
543 /* Create user profile directory */
545 StringCbCopyW(szUserProfilePath
, sizeof(szUserProfilePath
), szProfilesPath
);
546 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), L
"\\");
547 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), szUserProfileName
);
550 if (!CreateDirectoryW(szUserProfilePath
, NULL
))
552 if (GetLastError() != ERROR_ALREADY_EXISTS
)
554 DPRINT1("Error: %lu\n", GetLastError());
558 for (i
= 0; i
< 1000; i
++)
560 swprintf(szUserProfileName
, L
"%s.%03u", lpUserName
, i
);
562 StringCbCopyW(szUserProfilePath
, sizeof(szUserProfilePath
), szProfilesPath
);
563 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), L
"\\");
564 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), szUserProfileName
);
567 if (CreateDirectoryW(szUserProfilePath
, NULL
))
570 if (GetLastError() != ERROR_ALREADY_EXISTS
)
572 DPRINT1("Error: %lu\n", GetLastError());
578 /* Copy default user directory */
580 StringCbCopyW(szDefaultUserPath
, sizeof(szDefaultUserPath
), szProfilesPath
);
581 StringCbCatW(szDefaultUserPath
, sizeof(szDefaultUserPath
), L
"\\");
582 StringCbCatW(szDefaultUserPath
, sizeof(szDefaultUserPath
), szBuffer
);
585 if (!CopyDirectory(szUserProfilePath
, szDefaultUserPath
))
587 DPRINT1("Error: %lu\n", GetLastError());
591 /* Add profile to profile list */
592 if (!ConvertSidToStringSidW(pSid
,
595 DPRINT1("Error: %lu\n", GetLastError());
599 StringCbCopyW(szBuffer
, sizeof(szBuffer
),
600 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
601 StringCbCatW(szBuffer
, sizeof(szBuffer
), SidString
);
603 /* Create user profile key */
604 Error
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
608 REG_OPTION_NON_VOLATILE
,
613 if (Error
!= ERROR_SUCCESS
)
615 DPRINT1("Error: %lu\n", Error
);
620 /* Create non-expanded user profile path */
621 StringCbCopyW(szBuffer
, sizeof(szBuffer
), szRawProfilesPath
);
622 StringCbCatW(szBuffer
, sizeof(szBuffer
), L
"\\");
623 StringCbCatW(szBuffer
, sizeof(szBuffer
), szUserProfileName
);
625 /* Set 'ProfileImagePath' value (non-expanded) */
626 Error
= RegSetValueExW(hKey
,
631 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
632 if (Error
!= ERROR_SUCCESS
)
634 DPRINT1("Error: %lu\n", Error
);
640 /* Set 'Sid' value */
641 Error
= RegSetValueExW(hKey
,
647 if (Error
!= ERROR_SUCCESS
)
649 DPRINT1("Error: %lu\n", Error
);
657 /* Create user hive file */
659 /* Use the default hive file name */
660 StringCbCopyW(szBuffer
, sizeof(szBuffer
), szUserProfilePath
);
661 StringCbCatW(szBuffer
, sizeof(szBuffer
), L
"\\ntuser.dat");
663 /* Acquire restore privilege */
664 if (!AcquireRemoveRestorePrivilege(TRUE
))
666 Error
= GetLastError();
667 DPRINT1("Error: %lu\n", Error
);
672 /* Load the user hive */
673 Error
= RegLoadKeyW(HKEY_USERS
,
676 AcquireRemoveRestorePrivilege(FALSE
);
677 if (Error
!= ERROR_SUCCESS
)
679 DPRINT1("Error: %lu\n", Error
);
684 /* Initialize user hive */
685 if (!CreateUserHive(SidString
, szUserProfilePath
))
687 Error
= GetLastError();
688 DPRINT1("Error: %lu\n", Error
);
692 /* Unload the hive */
693 AcquireRemoveRestorePrivilege(TRUE
);
694 RegUnLoadKeyW(HKEY_USERS
, SidString
);
695 AcquireRemoveRestorePrivilege(FALSE
);
698 * If the caller wants to retrieve the user profile path,
699 * give it now. 'dwDirSize' is the number of characters.
701 if (lpProfileDir
&& dwDirSize
)
702 StringCchCopyW(lpProfileDir
, dwDirSize
, szUserProfilePath
);
705 LocalFree((HLOCAL
)SidString
);
706 SetLastError((DWORD
)Error
);
708 DPRINT("CreateUserProfileExW() done\n");
717 _In_ LPCSTR lpSidString
,
718 _In_opt_ LPCSTR lpProfilePath
,
719 _In_opt_ LPCSTR lpComputerName
)
722 UNICODE_STRING SidString
, ProfilePath
, ComputerName
;
724 DPRINT("DeleteProfileA() called\n");
726 /* Conversion to UNICODE */
728 RtlCreateUnicodeStringFromAsciiz(&SidString
,
732 RtlCreateUnicodeStringFromAsciiz(&ProfilePath
,
733 (LPSTR
)lpProfilePath
);
736 RtlCreateUnicodeStringFromAsciiz(&ComputerName
,
737 (LPSTR
)lpComputerName
);
739 /* Call the UNICODE function */
740 bResult
= DeleteProfileW(SidString
.Buffer
,
742 ComputerName
.Buffer
);
746 RtlFreeUnicodeString(&SidString
);
749 RtlFreeUnicodeString(&ProfilePath
);
752 RtlFreeUnicodeString(&ComputerName
);
761 _In_ LPCWSTR lpSidString
,
762 _In_opt_ LPCWSTR lpProfilePath
,
763 _In_opt_ LPCWSTR lpComputerName
)
765 DPRINT1("DeleteProfileW() not implemented!\n");
772 GetAllUsersProfileDirectoryA(
773 _Out_opt_ LPSTR lpProfileDir
,
774 _Inout_ LPDWORD lpcchSize
)
781 SetLastError(ERROR_INVALID_PARAMETER
);
785 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
786 *lpcchSize
* sizeof(WCHAR
));
787 if (lpBuffer
== NULL
)
790 bResult
= GetAllUsersProfileDirectoryW(lpBuffer
,
792 if (bResult
&& lpProfileDir
)
794 bResult
= WideCharToMultiByte(CP_ACP
,
804 GlobalFree(lpBuffer
);
812 GetAllUsersProfileDirectoryW(
813 _Out_opt_ LPWSTR lpProfileDir
,
814 _Inout_ LPDWORD lpcchSize
)
816 WCHAR szProfilePath
[MAX_PATH
];
817 WCHAR szBuffer
[MAX_PATH
];
818 DWORD dwType
, dwLength
;
824 SetLastError(ERROR_INVALID_PARAMETER
);
828 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
829 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
833 if (Error
!= ERROR_SUCCESS
)
835 DPRINT1("Error: %lu\n", Error
);
836 SetLastError((DWORD
)Error
);
840 /* Get profiles path */
841 dwLength
= sizeof(szBuffer
);
842 Error
= RegQueryValueExW(hKey
,
843 L
"ProfilesDirectory",
848 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
850 DPRINT1("Error: %lu\n", Error
);
852 SetLastError((DWORD
)Error
);
857 if (!ExpandEnvironmentStringsW(szBuffer
,
859 ARRAYSIZE(szProfilePath
)))
861 DPRINT1("Error: %lu\n", GetLastError());
866 /* Get 'AllUsersProfile' name */
867 dwLength
= sizeof(szBuffer
);
868 Error
= RegQueryValueExW(hKey
,
874 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
876 DPRINT1("Error: %lu\n", Error
);
878 SetLastError((DWORD
)Error
);
884 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), L
"\\");
885 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), szBuffer
);
887 dwLength
= wcslen(szProfilePath
) + 1;
888 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
890 StringCchCopyW(lpProfileDir
, *lpcchSize
, szProfilePath
);
891 *lpcchSize
= dwLength
;
894 else // if (!lpProfileDir || (*lpcchSize < dwLength))
896 *lpcchSize
= dwLength
;
897 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
905 GetDefaultUserProfileDirectoryA(
906 _Out_opt_ LPSTR lpProfileDir
,
907 _Inout_ LPDWORD lpcchSize
)
914 SetLastError(ERROR_INVALID_PARAMETER
);
918 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
919 *lpcchSize
* sizeof(WCHAR
));
920 if (lpBuffer
== NULL
)
923 bResult
= GetDefaultUserProfileDirectoryW(lpBuffer
,
925 if (bResult
&& lpProfileDir
)
927 bResult
= WideCharToMultiByte(CP_ACP
,
937 GlobalFree(lpBuffer
);
945 GetDefaultUserProfileDirectoryW(
946 _Out_opt_ LPWSTR lpProfileDir
,
947 _Inout_ LPDWORD lpcchSize
)
949 WCHAR szProfilePath
[MAX_PATH
];
950 WCHAR szBuffer
[MAX_PATH
];
951 DWORD dwType
, dwLength
;
957 SetLastError(ERROR_INVALID_PARAMETER
);
961 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
962 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
966 if (Error
!= ERROR_SUCCESS
)
968 DPRINT1("Error: %lu\n", Error
);
969 SetLastError((DWORD
)Error
);
973 /* Get profiles path */
974 dwLength
= sizeof(szBuffer
);
975 Error
= RegQueryValueExW(hKey
,
976 L
"ProfilesDirectory",
981 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
983 DPRINT1("Error: %lu\n", Error
);
985 SetLastError((DWORD
)Error
);
990 if (!ExpandEnvironmentStringsW(szBuffer
,
992 ARRAYSIZE(szProfilePath
)))
994 DPRINT1("Error: %lu\n", GetLastError());
999 /* Get 'DefaultUserProfile' name */
1000 dwLength
= sizeof(szBuffer
);
1001 Error
= RegQueryValueExW(hKey
,
1002 L
"DefaultUserProfile",
1007 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1009 DPRINT1("Error: %lu\n", Error
);
1011 SetLastError((DWORD
)Error
);
1017 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), L
"\\");
1018 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), szBuffer
);
1020 dwLength
= wcslen(szProfilePath
) + 1;
1021 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1023 StringCchCopyW(lpProfileDir
, *lpcchSize
, szProfilePath
);
1024 *lpcchSize
= dwLength
;
1027 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1029 *lpcchSize
= dwLength
;
1030 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1038 GetProfilesDirectoryA(
1039 _Out_ LPSTR lpProfileDir
, // _Out_opt_
1040 _Inout_ LPDWORD lpcchSize
)
1047 SetLastError(ERROR_INVALID_PARAMETER
);
1051 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1052 *lpcchSize
* sizeof(WCHAR
));
1053 if (lpBuffer
== NULL
)
1056 bResult
= GetProfilesDirectoryW(lpBuffer
,
1058 if (bResult
&& lpProfileDir
)
1060 bResult
= WideCharToMultiByte(CP_ACP
,
1070 GlobalFree(lpBuffer
);
1078 GetProfilesDirectoryW(
1079 _Out_ LPWSTR lpProfilesDir
, // _Out_opt_
1080 _Inout_ LPDWORD lpcchSize
)
1082 WCHAR szProfilesPath
[MAX_PATH
];
1083 WCHAR szBuffer
[MAX_PATH
];
1084 DWORD dwType
, dwLength
;
1090 SetLastError(ERROR_INVALID_PARAMETER
);
1094 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1095 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1099 if (Error
!= ERROR_SUCCESS
)
1101 DPRINT1("Error: %lu\n", Error
);
1102 SetLastError((DWORD
)Error
);
1106 /* Get profiles path */
1107 dwLength
= sizeof(szBuffer
);
1108 Error
= RegQueryValueExW(hKey
,
1109 L
"ProfilesDirectory",
1114 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1116 DPRINT1("Error: %lu\n", Error
);
1118 SetLastError((DWORD
)Error
);
1125 if (!ExpandEnvironmentStringsW(szBuffer
,
1127 ARRAYSIZE(szProfilesPath
)))
1129 DPRINT1("Error: %lu\n", GetLastError());
1133 dwLength
= wcslen(szProfilesPath
) + 1;
1134 if (lpProfilesDir
&& (*lpcchSize
>= dwLength
))
1136 StringCchCopyW(lpProfilesDir
, *lpcchSize
, szProfilesPath
);
1137 *lpcchSize
= dwLength
;
1140 else // if (!lpProfilesDir || (*lpcchSize < dwLength))
1142 *lpcchSize
= dwLength
;
1143 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1152 _Out_ PDWORD pdwFlags
)
1154 DPRINT1("GetProfileType() not implemented!\n");
1161 GetUserProfileDirectoryA(
1163 _Out_opt_ LPSTR lpProfileDir
,
1164 _Inout_ LPDWORD lpcchSize
)
1171 SetLastError(ERROR_INVALID_PARAMETER
);
1175 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1176 *lpcchSize
* sizeof(WCHAR
));
1177 if (lpBuffer
== NULL
)
1180 bResult
= GetUserProfileDirectoryW(hToken
,
1183 if (bResult
&& lpProfileDir
)
1185 bResult
= WideCharToMultiByte(CP_ACP
,
1195 GlobalFree(lpBuffer
);
1203 GetUserProfileDirectoryW(
1205 _Out_opt_ LPWSTR lpProfileDir
,
1206 _Inout_ LPDWORD lpcchSize
)
1208 UNICODE_STRING SidString
;
1209 WCHAR szKeyName
[MAX_PATH
];
1210 WCHAR szRawImagePath
[MAX_PATH
];
1211 WCHAR szImagePath
[MAX_PATH
];
1212 DWORD dwType
, dwLength
;
1218 SetLastError(ERROR_INVALID_HANDLE
);
1224 SetLastError(ERROR_INVALID_PARAMETER
);
1228 /* Get the user SID string */
1229 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1231 DPRINT1("GetUserSidStringFromToken() failed\n");
1235 DPRINT("SidString: '%wZ'\n", &SidString
);
1237 StringCbCopyW(szKeyName
, sizeof(szKeyName
),
1238 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
1239 StringCbCatW(szKeyName
, sizeof(szKeyName
), SidString
.Buffer
);
1241 RtlFreeUnicodeString(&SidString
);
1243 DPRINT("KeyName: '%S'\n", szKeyName
);
1245 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1250 if (Error
!= ERROR_SUCCESS
)
1252 DPRINT1("Error: %lu\n", Error
);
1253 SetLastError((DWORD
)Error
);
1257 dwLength
= sizeof(szRawImagePath
);
1258 Error
= RegQueryValueExW(hKey
,
1259 L
"ProfileImagePath",
1262 (LPBYTE
)szRawImagePath
,
1264 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1266 DPRINT1("Error: %lu\n", Error
);
1268 SetLastError((DWORD
)Error
);
1274 DPRINT("RawImagePath: '%S'\n", szRawImagePath
);
1277 if (!ExpandEnvironmentStringsW(szRawImagePath
,
1279 ARRAYSIZE(szImagePath
)))
1281 DPRINT1("Error: %lu\n", GetLastError());
1285 DPRINT("ImagePath: '%S'\n", szImagePath
);
1287 dwLength
= wcslen(szImagePath
) + 1;
1288 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1290 StringCchCopyW(lpProfileDir
, *lpcchSize
, szImagePath
);
1291 *lpcchSize
= dwLength
;
1294 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1296 *lpcchSize
= dwLength
;
1297 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1307 _Inout_ LPPROFILEINFOA lpProfileInfo
)
1309 BOOL bResult
= FALSE
;
1310 PROFILEINFOW ProfileInfoW
= {0};
1313 DPRINT("LoadUserProfileA() called\n");
1315 /* Check profile info */
1316 if (!lpProfileInfo
|| (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOA
)) ||
1317 (lpProfileInfo
->lpUserName
== NULL
) || (lpProfileInfo
->lpUserName
[0] == 0))
1319 SetLastError(ERROR_INVALID_PARAMETER
);
1323 /* Convert the structure to UNICODE... */
1324 ProfileInfoW
.dwSize
= sizeof(ProfileInfoW
);
1325 ProfileInfoW
.dwFlags
= lpProfileInfo
->dwFlags
;
1327 if (lpProfileInfo
->lpUserName
)
1329 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpUserName
, -1, NULL
, 0);
1330 ProfileInfoW
.lpUserName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1331 if (!ProfileInfoW
.lpUserName
)
1333 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1336 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpUserName
, -1, ProfileInfoW
.lpUserName
, len
);
1339 if (lpProfileInfo
->lpProfilePath
)
1341 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpProfilePath
, -1, NULL
, 0);
1342 ProfileInfoW
.lpProfilePath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1343 if (!ProfileInfoW
.lpProfilePath
)
1345 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1348 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpProfilePath
, -1, ProfileInfoW
.lpProfilePath
, len
);
1351 if (lpProfileInfo
->lpDefaultPath
)
1353 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpDefaultPath
, -1, NULL
, 0);
1354 ProfileInfoW
.lpDefaultPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1355 if (!ProfileInfoW
.lpDefaultPath
)
1357 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1360 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpDefaultPath
, -1, ProfileInfoW
.lpDefaultPath
, len
);
1363 if (lpProfileInfo
->lpServerName
)
1365 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpServerName
, -1, NULL
, 0);
1366 ProfileInfoW
.lpServerName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1367 if (!ProfileInfoW
.lpServerName
)
1369 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1372 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpServerName
, -1, ProfileInfoW
.lpServerName
, len
);
1375 if ((ProfileInfoW
.dwFlags
& PI_APPLYPOLICY
) != 0 && lpProfileInfo
->lpPolicyPath
)
1377 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpPolicyPath
, -1, NULL
, 0);
1378 ProfileInfoW
.lpPolicyPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1379 if (!ProfileInfoW
.lpPolicyPath
)
1381 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1384 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpPolicyPath
, -1, ProfileInfoW
.lpPolicyPath
, len
);
1387 /* ... and call the UNICODE function */
1388 bResult
= LoadUserProfileW(hToken
, &ProfileInfoW
);
1390 /* Save the returned value */
1391 lpProfileInfo
->hProfile
= ProfileInfoW
.hProfile
;
1394 /* Memory cleanup */
1395 if (ProfileInfoW
.lpUserName
)
1396 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpUserName
);
1398 if (ProfileInfoW
.lpProfilePath
)
1399 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpProfilePath
);
1401 if (ProfileInfoW
.lpDefaultPath
)
1402 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpDefaultPath
);
1404 if (ProfileInfoW
.lpServerName
)
1405 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpServerName
);
1407 if ((ProfileInfoW
.dwFlags
& PI_APPLYPOLICY
) != 0 && ProfileInfoW
.lpPolicyPath
)
1408 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpPolicyPath
);
1418 _Inout_ LPPROFILEINFOW lpProfileInfo
)
1420 WCHAR szUserHivePath
[MAX_PATH
];
1421 PTOKEN_USER UserSid
= NULL
;
1422 UNICODE_STRING SidString
= { 0, 0, NULL
};
1425 DWORD dwLength
= sizeof(szUserHivePath
) / sizeof(szUserHivePath
[0]);
1427 DPRINT("LoadUserProfileW(%p %p)\n", hToken
, lpProfileInfo
);
1429 /* Check profile info */
1430 if (!lpProfileInfo
|| (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOW
)) ||
1431 (lpProfileInfo
->lpUserName
== NULL
) || (lpProfileInfo
->lpUserName
[0] == 0))
1433 SetLastError(ERROR_INVALID_PARAMETER
);
1437 DPRINT("UserName: %S\n", lpProfileInfo
->lpUserName
);
1439 /* Get the user SID string */
1440 ret
= GetUserSidStringFromToken(hToken
, &SidString
);
1443 DPRINT1("GetUserSidStringFromToken() failed\n");
1448 /* Don't load a profile twice */
1449 if (CheckForLoadedProfile(hToken
))
1451 DPRINT1("Profile %S already loaded\n", SidString
.Buffer
);
1455 DPRINT1("Loading profile %S\n", SidString
.Buffer
);
1457 if (lpProfileInfo
->lpProfilePath
)
1459 /* Use the caller's specified roaming user profile path */
1460 StringCbCopyW(szUserHivePath
, sizeof(szUserHivePath
), lpProfileInfo
->lpProfilePath
);
1464 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
1465 if (!GetProfilesDirectoryW(szUserHivePath
, &dwLength
))
1467 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
1472 /* Create user hive name */
1473 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\");
1474 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), lpProfileInfo
->lpUserName
);
1475 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\ntuser.dat");
1476 DPRINT("szUserHivePath: %S\n", szUserHivePath
);
1478 /* Create user profile directory if needed */
1479 if (GetFileAttributesW(szUserHivePath
) == INVALID_FILE_ATTRIBUTES
)
1482 if (GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &dwLength
) ||
1483 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1485 DPRINT1 ("GetTokenInformation() failed\n");
1489 UserSid
= (PTOKEN_USER
)HeapAlloc(GetProcessHeap(), 0, dwLength
);
1492 DPRINT1("HeapAlloc() failed\n");
1493 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1497 if (!GetTokenInformation(hToken
, TokenUser
, UserSid
, dwLength
, &dwLength
))
1499 DPRINT1("GetTokenInformation() failed\n");
1503 /* Create profile */
1504 ret
= CreateUserProfileW(UserSid
->User
.Sid
, lpProfileInfo
->lpUserName
);
1507 DPRINT1("CreateUserProfileW() failed\n");
1512 /* Acquire restore privilege */
1513 if (!AcquireRemoveRestorePrivilege(TRUE
))
1515 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1519 /* Load user registry hive */
1520 Error
= RegLoadKeyW(HKEY_USERS
,
1523 AcquireRemoveRestorePrivilege(FALSE
);
1525 /* HACK: Do not fail if the profile has already been loaded! */
1526 if (Error
== ERROR_SHARING_VIOLATION
)
1527 Error
= ERROR_SUCCESS
;
1529 if (Error
!= ERROR_SUCCESS
)
1531 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error
);
1532 SetLastError((DWORD
)Error
);
1537 /* Open future HKEY_CURRENT_USER */
1538 Error
= RegOpenKeyExW(HKEY_USERS
,
1542 (PHKEY
)&lpProfileInfo
->hProfile
);
1543 if (Error
!= ERROR_SUCCESS
)
1545 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error
);
1546 SetLastError((DWORD
)Error
);
1553 if (UserSid
!= NULL
)
1554 HeapFree(GetProcessHeap(), 0, UserSid
);
1555 RtlFreeUnicodeString(&SidString
);
1557 DPRINT("LoadUserProfileW() done\n");
1566 _In_ HANDLE hProfile
)
1568 UNICODE_STRING SidString
;
1571 DPRINT("UnloadUserProfile() called\n");
1573 if (hProfile
== NULL
)
1575 DPRINT1("Invalid profile handle\n");
1576 SetLastError(ERROR_INVALID_PARAMETER
);
1580 RegCloseKey(hProfile
);
1582 /* Get the user SID string */
1583 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1585 DPRINT1("GetUserSidStringFromToken() failed\n");
1589 DPRINT("SidString: '%wZ'\n", &SidString
);
1591 /* Acquire restore privilege */
1592 if (!AcquireRemoveRestorePrivilege(TRUE
))
1594 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1595 RtlFreeUnicodeString(&SidString
);
1603 Error
= RegOpenKeyExW(HKEY_USERS
,
1608 if (Error
== ERROR_SUCCESS
)
1610 RegDeleteKeyW(hUserKey
,
1611 L
"Volatile Environment");
1613 RegCloseKey(hUserKey
);
1618 /* Unload the hive */
1619 Error
= RegUnLoadKeyW(HKEY_USERS
,
1622 /* Remove restore privilege */
1623 AcquireRemoveRestorePrivilege(FALSE
);
1625 if (Error
!= ERROR_SUCCESS
)
1627 DPRINT1("RegUnLoadKeyW() failed (Error %ld)\n", Error
);
1628 RtlFreeUnicodeString(&SidString
);
1629 SetLastError((DWORD
)Error
);
1633 RtlFreeUnicodeString(&SidString
);
1635 DPRINT("UnloadUserProfile() done\n");