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");
149 _In_ PWSTR pszSidString
)
151 SECURITY_DESCRIPTOR SecurityDescriptor
;
152 SECURITY_ATTRIBUTES SecurityAttributes
;
153 PWSTR pszMutexName
= NULL
;
154 HANDLE hMutex
= NULL
;
156 pszMutexName
= HeapAlloc(GetProcessHeap(),
158 (wcslen(L
"Global\\userenv: User Profile Mutex for ") + wcslen(pszSidString
) + 1) * sizeof(WCHAR
));
159 if (pszMutexName
== NULL
)
161 DPRINT("Failed to allocate the mutex name buffer!\n");
162 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
166 /* Build the profile mutex name */
167 wcscpy(pszMutexName
, L
"Global\\userenv: User Profile Mutex for ");
168 wcscat(pszMutexName
, pszSidString
);
170 /* Initialize the security descriptor */
171 InitializeSecurityDescriptor(&SecurityDescriptor
,
172 SECURITY_DESCRIPTOR_REVISION
);
174 /* Set a NULL-DACL (everyone has access) */
175 SetSecurityDescriptorDacl(&SecurityDescriptor
,
180 /* Initialize the security attributes */
181 SecurityAttributes
.nLength
= sizeof(SecurityAttributes
);
182 SecurityAttributes
.lpSecurityDescriptor
= &SecurityDescriptor
;
183 SecurityAttributes
.bInheritHandle
= FALSE
;
185 /* Create the profile mutex */
186 hMutex
= CreateMutexW(&SecurityAttributes
,
191 DPRINT1("Failed to create the profile mutex (Error %lu)\n", GetLastError());
194 HeapFree(GetProcessHeap(), 0, pszMutexName
);
206 HKEY hProfilesKey
= NULL
, hProfileKey
= NULL
;
207 DWORD dwRefCount
= 0, dwLength
, dwType
;
210 DPRINT1("IncrementRefCount(%S %p)\n",
211 pszSidString
, pdwRefCount
);
213 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
214 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
218 if (dwError
!= ERROR_SUCCESS
)
220 DPRINT1("Error: %lu\n", dwError
);
224 dwError
= RegOpenKeyExW(hProfilesKey
,
227 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
229 if (dwError
!= ERROR_SUCCESS
)
231 DPRINT1("Error: %lu\n", dwError
);
235 /* Get the reference counter */
236 dwLength
= sizeof(dwRefCount
);
237 RegQueryValueExW(hProfileKey
,
246 dwLength
= sizeof(dwRefCount
);
247 dwError
= RegSetValueExW(hProfileKey
,
253 if (dwError
!= ERROR_SUCCESS
)
255 DPRINT1("Error: %lu\n", dwError
);
259 if (pdwRefCount
!= NULL
)
260 *pdwRefCount
= dwRefCount
;
263 if (hProfileKey
!= NULL
)
264 RegCloseKey(hProfileKey
);
266 if (hProfilesKey
!= NULL
)
267 RegCloseKey(hProfilesKey
);
279 HKEY hProfilesKey
= NULL
, hProfileKey
= NULL
;
280 DWORD dwRefCount
= 0, dwLength
, dwType
;
283 DPRINT1("DecrementRefCount(%S %p)\n",
284 pszSidString
, pdwRefCount
);
286 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
287 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
291 if (dwError
!= ERROR_SUCCESS
)
293 DPRINT1("Error: %lu\n", dwError
);
297 dwError
= RegOpenKeyExW(hProfilesKey
,
300 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
302 if (dwError
!= ERROR_SUCCESS
)
304 DPRINT1("Error: %lu\n", dwError
);
308 /* Get the reference counter */
309 dwLength
= sizeof(dwRefCount
);
310 dwError
= RegQueryValueExW(hProfileKey
,
316 if (dwError
!= ERROR_SUCCESS
)
318 DPRINT1("Error: %lu\n", dwError
);
324 dwLength
= sizeof(dwRefCount
);
325 dwError
= RegSetValueExW(hProfileKey
,
331 if (dwError
!= ERROR_SUCCESS
)
333 DPRINT1("Error: %lu\n", dwError
);
337 if (pdwRefCount
!= NULL
)
338 *pdwRefCount
= dwRefCount
;
341 if (hProfileKey
!= NULL
)
342 RegCloseKey(hProfileKey
);
344 if (hProfilesKey
!= NULL
)
345 RegCloseKey(hProfilesKey
);
353 CheckForGuestsAndAdmins(
355 _Out_ PDWORD pdwState
)
357 PTOKEN_GROUPS pGroupInfo
= NULL
;
358 PSID pAdministratorsSID
= NULL
;
359 PSID pGuestsSID
= NULL
;
361 DWORD dwError
= ERROR_SUCCESS
;
363 DPRINT("CheckForGuestsAndAdmins(%p %p)\n", hToken
, pdwState
);
365 /* Get the buffer size */
366 if (!GetTokenInformation(hToken
, TokenGroups
, NULL
, dwSize
, &dwSize
))
368 dwError
= GetLastError();
369 if (dwError
!= ERROR_INSUFFICIENT_BUFFER
)
371 DPRINT1("GetTokenInformation() failed (Error %lu)\n", dwError
);
375 dwError
= ERROR_SUCCESS
;
378 /* Allocate the buffer */
379 pGroupInfo
= (PTOKEN_GROUPS
)HeapAlloc(GetProcessHeap(), 0, dwSize
);
380 if (pGroupInfo
== NULL
)
382 dwError
= ERROR_OUTOFMEMORY
;
383 DPRINT1("HeapAlloc() failed (Error %lu)\n", dwError
);
387 /* Get the token groups */
388 if (!GetTokenInformation(hToken
, TokenGroups
, pGroupInfo
, dwSize
, &dwSize
))
390 dwError
= GetLastError();
391 DPRINT1("GetTokenInformation() failed (Error %lu)\n", dwError
);
395 /* Build the Administrators Group SID */
396 if(!AllocateAndInitializeSid(&LocalSystemAuthority
,
398 SECURITY_BUILTIN_DOMAIN_RID
,
399 DOMAIN_ALIAS_RID_ADMINS
,
401 &pAdministratorsSID
))
403 dwError
= GetLastError();
404 DPRINT1("AllocateAndInitializeSid() failed (Error %lu)\n", dwError
);
408 /* Build the Guests Group SID */
409 if(!AllocateAndInitializeSid(&LocalSystemAuthority
,
411 SECURITY_BUILTIN_DOMAIN_RID
,
412 DOMAIN_ALIAS_RID_GUESTS
,
416 dwError
= GetLastError();
417 DPRINT1("AllocateAndInitializeSid() failed (Error %lu)\n", dwError
);
421 /* Check for Administratos or Guests group memberships */
422 for (i
= 0; i
< pGroupInfo
->GroupCount
; i
++)
424 if (EqualSid(pAdministratorsSID
, pGroupInfo
->Groups
[i
].Sid
))
426 *pdwState
|= 0x0100; // PROFILE_ADMIN_USER
429 if (EqualSid(pGuestsSID
, pGroupInfo
->Groups
[i
].Sid
))
431 *pdwState
|= 0x0080; // PROFILE_GUESTS_USER
435 dwError
= ERROR_SUCCESS
;
438 if (pGuestsSID
!= NULL
)
441 if (pAdministratorsSID
!= NULL
)
442 FreeSid(pAdministratorsSID
);
444 if (pGroupInfo
!= NULL
)
445 HeapFree(GetProcessHeap(), 0, pGroupInfo
);
454 _In_ PWSTR pszSidString
,
458 HKEY hProfilesKey
= NULL
, hProfileKey
= NULL
;
460 DWORD dwLength
, dwState
= 0;
463 DPRINT("SetProfileData(%S %p)\n", pszSidString
, hToken
);
465 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
466 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
470 if (dwError
!= ERROR_SUCCESS
)
472 DPRINT1("Error: %lu\n", dwError
);
476 dwError
= RegOpenKeyExW(hProfilesKey
,
479 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
481 if (dwError
!= ERROR_SUCCESS
)
483 DPRINT1("Error: %lu\n", dwError
);
487 /* Set the profile load time */
488 GetSystemTimeAsFileTime(&LoadTime
);
490 dwLength
= sizeof(LoadTime
.dwLowDateTime
);
491 dwError
= RegSetValueExW(hProfileKey
,
492 L
"ProfileLoadTimeLow",
495 (PBYTE
)&LoadTime
.dwLowDateTime
,
497 if (dwError
!= ERROR_SUCCESS
)
499 DPRINT1("Error: %lu\n", dwError
);
503 dwLength
= sizeof(LoadTime
.dwHighDateTime
);
504 dwError
= RegSetValueExW(hProfileKey
,
505 L
"ProfileLoadTimeHigh",
508 (PBYTE
)&LoadTime
.dwHighDateTime
,
510 if (dwError
!= ERROR_SUCCESS
)
512 DPRINT1("Error: %lu\n", dwError
);
516 dwLength
= sizeof(dwFlags
);
517 dwError
= RegSetValueExW(hProfileKey
,
523 if (dwError
!= ERROR_SUCCESS
)
525 DPRINT1("Error: %lu\n", dwError
);
529 dwError
= CheckForGuestsAndAdmins(hToken
,
531 if (dwError
!= ERROR_SUCCESS
)
533 DPRINT1("Error: %lu\n", dwError
);
537 dwLength
= sizeof(dwState
);
538 dwError
= RegSetValueExW(hProfileKey
,
544 if (dwError
!= ERROR_SUCCESS
)
546 DPRINT1("Error: %lu\n", dwError
);
551 if (hProfileKey
!= NULL
)
552 RegCloseKey(hProfileKey
);
554 if (hProfilesKey
!= NULL
)
555 RegCloseKey(hProfilesKey
);
561 /* PUBLIC FUNCTIONS ********************************************************/
568 WCHAR szKeyName
[MAX_PATH
];
569 WCHAR szRawProfilePath
[MAX_PATH
];
570 WCHAR szProfilePath
[MAX_PATH
];
571 WCHAR szDefaultProfilePath
[MAX_PATH
];
572 UNICODE_STRING SidString
= {0, 0, NULL
};
573 HANDLE hToken
= NULL
;
574 PSID pUserSid
= NULL
;
575 HKEY hProfileKey
= NULL
;
577 BOOL bResult
= FALSE
;
581 DPRINT1("CopySystemProfile()\n");
583 if (!OpenProcessToken(GetCurrentProcess(),
584 TOKEN_QUERY
| TOKEN_IMPERSONATE
,
587 DPRINT1("Failed to open the process token (Error %lu)\n", GetLastError());
591 pUserSid
= GetUserSid(hToken
);
592 if (pUserSid
== NULL
)
594 DPRINT1("Failed to get the users SID (Error %lu)\n", GetLastError());
598 /* Get the user SID string */
599 if (!GetUserSidStringFromToken(hToken
, &SidString
))
601 DPRINT1("GetUserSidStringFromToken() failed\n");
605 StringCbCopyW(szKeyName
, sizeof(szKeyName
),
606 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
607 StringCbCatW(szKeyName
, sizeof(szKeyName
), SidString
.Buffer
);
609 RtlFreeUnicodeString(&SidString
);
611 dwError
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
618 if (dwError
!= ERROR_SUCCESS
)
620 DPRINT1("Failed to create the profile key for the %s profile (Error %lu)\n",
621 SidString
.Buffer
, dwError
);
625 dwError
= RegSetValueExW(hProfileKey
,
630 RtlLengthSid(pUserSid
));
631 if (dwError
!= ERROR_SUCCESS
)
633 DPRINT1("Failed to set the SID value (Error %lu)\n", dwError
);
637 wcscpy(szRawProfilePath
,
638 L
"%systemroot%\\system32\\config\\systemprofile");
640 dwError
= RegSetValueExW(hProfileKey
,
644 (PBYTE
)szRawProfilePath
,
645 (wcslen(szRawProfilePath
) + 1) * sizeof(WCHAR
));
646 if (dwError
!= ERROR_SUCCESS
)
648 DPRINT1("Failed to set the ProfileImagePath value (Error %lu)\n", dwError
);
652 /* Expand the raw profile path */
653 if (!ExpandEnvironmentStringsW(szRawProfilePath
,
655 ARRAYSIZE(szProfilePath
)))
657 DPRINT1("Failled to expand the raw profile path (Error %lu)\n", GetLastError());
661 /* Create the profile directory if it does not exist yet */
663 if (!CreateDirectoryW(szProfilePath
, NULL
))
665 if (GetLastError() != ERROR_ALREADY_EXISTS
)
667 DPRINT1("Failed to create the profile directory (Error %lu)\n", GetLastError());
672 /* Get the path of the default profile */
673 cchSize
= ARRAYSIZE(szDefaultProfilePath
);
674 if (!GetDefaultUserProfileDirectoryW(szDefaultProfilePath
, &cchSize
))
676 DPRINT1("Failed to create the default profile path (Error %lu)\n", GetLastError());
680 /* Copy the default profile into the new profile directory */
682 if (!CopyDirectory(szProfilePath
, szDefaultProfilePath
))
684 DPRINT1("Failed to copy the default profile directory (Error %lu)\n", GetLastError());
691 if (hProfileKey
!= NULL
)
692 RegCloseKey(hProfileKey
);
694 RtlFreeUnicodeString(&SidString
);
696 if (pUserSid
!= NULL
)
710 _In_ LPCSTR lpUserName
)
712 LPWSTR pUserNameW
= NULL
;
716 DPRINT("CreateUserProfileA(%p %s)\n", pSid
, lpUserName
);
718 /* Convert lpUserName to Unicode */
719 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, NULL
, 0);
720 pUserNameW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
721 if (pUserNameW
== NULL
)
723 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
726 MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, pUserNameW
, nLength
);
728 /* Call the Ex function */
729 bResult
= CreateUserProfileExW(pSid
,
736 HeapFree(GetProcessHeap(), 0, pUserNameW
);
746 _In_ LPCWSTR lpUserName
)
748 DPRINT("CreateUserProfileW(%p %S)\n", pSid
, lpUserName
);
750 /* Call the Ex function */
751 return CreateUserProfileExW(pSid
,
762 CreateUserProfileExA(
764 _In_ LPCSTR lpUserName
,
765 _In_opt_ LPCSTR lpUserHive
,
766 _Out_opt_ LPSTR lpProfileDir
,
767 _In_ DWORD dwDirSize
,
770 LPWSTR pUserNameW
= NULL
;
771 LPWSTR pUserHiveW
= NULL
;
772 LPWSTR pProfileDirW
= NULL
;
774 BOOL bResult
= FALSE
;
776 DPRINT("CreateUserProfileExA(%p %s %s %p %lu %d)\n",
777 pSid
, lpUserName
, lpUserHive
, lpProfileDir
, dwDirSize
, bWin9xUpg
);
779 /* Check the parameters */
780 if (lpProfileDir
!= NULL
&& dwDirSize
== 0)
782 SetLastError(ERROR_INVALID_PARAMETER
);
786 /* Convert lpUserName to Unicode */
787 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, NULL
, 0);
788 pUserNameW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
789 if (pUserNameW
== NULL
)
791 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
794 MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, pUserNameW
, nLength
);
796 /* Convert lpUserHive to Unicode */
797 if (lpUserHive
!= NULL
)
799 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserHive
, -1, NULL
, 0);
800 pUserHiveW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
801 if (pUserHiveW
== NULL
)
803 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
806 MultiByteToWideChar(CP_ACP
, 0, lpUserHive
, -1, pUserHiveW
, nLength
);
809 /* Allocate a Unicode buffer for lpProfileDir */
810 if (lpProfileDir
!= NULL
)
812 pProfileDirW
= HeapAlloc(GetProcessHeap(), 0, dwDirSize
* sizeof(WCHAR
));
813 if (pProfileDirW
== NULL
)
815 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
820 /* Call the Unicode function */
821 bResult
= CreateUserProfileExW(pSid
,
828 /* Convert the profile path to ANSI */
829 if (bResult
&& lpProfileDir
!= NULL
)
831 WideCharToMultiByte(CP_ACP
, 0, pProfileDirW
, -1, lpProfileDir
, dwDirSize
, NULL
, NULL
);
835 /* Free the buffers */
836 if (pProfileDirW
!= NULL
)
837 HeapFree(GetProcessHeap(), 0, pProfileDirW
);
839 if (pUserHiveW
!= NULL
)
840 HeapFree(GetProcessHeap(), 0, pUserHiveW
);
842 if (pUserNameW
!= NULL
)
843 HeapFree(GetProcessHeap(), 0, pUserNameW
);
851 CreateUserProfileExW(
853 _In_ LPCWSTR lpUserName
,
854 _In_opt_ LPCWSTR lpUserHive
,
855 _Out_opt_ LPWSTR lpProfileDir
,
856 _In_ DWORD dwDirSize
,
859 WCHAR szRawProfilesPath
[MAX_PATH
];
860 WCHAR szProfilesPath
[MAX_PATH
];
861 WCHAR szUserProfilePath
[MAX_PATH
];
862 WCHAR szDefaultUserPath
[MAX_PATH
];
863 WCHAR szUserProfileName
[MAX_PATH
];
864 WCHAR szBuffer
[MAX_PATH
];
866 DWORD dwType
, dwLength
;
873 DPRINT("CreateUserProfileExW(%p %S %S %p %lu %d)\n",
874 pSid
, lpUserName
, lpUserHive
, lpProfileDir
, dwDirSize
, bWin9xUpg
);
876 /* Parameters validation */
877 if (!pSid
|| !lpUserName
)
879 SetLastError(ERROR_INVALID_PARAMETER
);
885 * - Add support for lpUserHive.
886 * - bWin9xUpg is obsolete. Don't waste your time implementing this.
889 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
890 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
894 if (Error
!= ERROR_SUCCESS
)
896 DPRINT1("Error: %lu\n", Error
);
897 SetLastError((DWORD
)Error
);
901 /* Get profiles path */
902 dwLength
= sizeof(szRawProfilesPath
);
903 Error
= RegQueryValueExW(hKey
,
904 L
"ProfilesDirectory",
907 (LPBYTE
)szRawProfilesPath
,
909 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
911 DPRINT1("Error: %lu\n", Error
);
913 SetLastError((DWORD
)Error
);
918 if (!ExpandEnvironmentStringsW(szRawProfilesPath
,
920 ARRAYSIZE(szProfilesPath
)))
922 DPRINT1("Error: %lu\n", GetLastError());
927 /* Create the profiles directory if it does not exist yet */
929 if (!CreateDirectoryW(szProfilesPath
, NULL
))
931 if (GetLastError() != ERROR_ALREADY_EXISTS
)
933 DPRINT1("Error: %lu\n", GetLastError());
938 /* Get default user path */
939 dwLength
= sizeof(szBuffer
);
940 Error
= RegQueryValueExW(hKey
,
941 L
"DefaultUserProfile",
946 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
948 DPRINT1("Error: %lu\n", Error
);
950 SetLastError((DWORD
)Error
);
956 StringCbCopyW(szUserProfileName
, sizeof(szUserProfileName
), lpUserName
);
958 /* Create user profile directory */
960 StringCbCopyW(szUserProfilePath
, sizeof(szUserProfilePath
), szProfilesPath
);
961 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), L
"\\");
962 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), szUserProfileName
);
965 if (!CreateDirectoryW(szUserProfilePath
, NULL
))
967 if (GetLastError() != ERROR_ALREADY_EXISTS
)
969 DPRINT1("Error: %lu\n", GetLastError());
973 for (i
= 0; i
< 1000; i
++)
975 swprintf(szUserProfileName
, L
"%s.%03u", lpUserName
, i
);
977 StringCbCopyW(szUserProfilePath
, sizeof(szUserProfilePath
), szProfilesPath
);
978 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), L
"\\");
979 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), szUserProfileName
);
982 if (CreateDirectoryW(szUserProfilePath
, NULL
))
985 if (GetLastError() != ERROR_ALREADY_EXISTS
)
987 DPRINT1("Error: %lu\n", GetLastError());
993 /* Copy default user directory */
995 StringCbCopyW(szDefaultUserPath
, sizeof(szDefaultUserPath
), szProfilesPath
);
996 StringCbCatW(szDefaultUserPath
, sizeof(szDefaultUserPath
), L
"\\");
997 StringCbCatW(szDefaultUserPath
, sizeof(szDefaultUserPath
), szBuffer
);
1000 if (!CopyDirectory(szUserProfilePath
, szDefaultUserPath
))
1002 DPRINT1("Error: %lu\n", GetLastError());
1006 /* Add profile to profile list */
1007 if (!ConvertSidToStringSidW(pSid
,
1010 DPRINT1("Error: %lu\n", GetLastError());
1014 StringCbCopyW(szBuffer
, sizeof(szBuffer
),
1015 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
1016 StringCbCatW(szBuffer
, sizeof(szBuffer
), SidString
);
1018 /* Create user profile key */
1019 Error
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
1023 REG_OPTION_NON_VOLATILE
,
1028 if (Error
!= ERROR_SUCCESS
)
1030 DPRINT1("Error: %lu\n", Error
);
1035 /* Create non-expanded user profile path */
1036 StringCbCopyW(szBuffer
, sizeof(szBuffer
), szRawProfilesPath
);
1037 StringCbCatW(szBuffer
, sizeof(szBuffer
), L
"\\");
1038 StringCbCatW(szBuffer
, sizeof(szBuffer
), szUserProfileName
);
1040 /* Set 'ProfileImagePath' value (non-expanded) */
1041 Error
= RegSetValueExW(hKey
,
1042 L
"ProfileImagePath",
1046 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
1047 if (Error
!= ERROR_SUCCESS
)
1049 DPRINT1("Error: %lu\n", Error
);
1055 /* Set 'Sid' value */
1056 Error
= RegSetValueExW(hKey
,
1061 GetLengthSid(pSid
));
1062 if (Error
!= ERROR_SUCCESS
)
1064 DPRINT1("Error: %lu\n", Error
);
1072 /* Create user hive file */
1074 /* Use the default hive file name */
1075 StringCbCopyW(szBuffer
, sizeof(szBuffer
), szUserProfilePath
);
1076 StringCbCatW(szBuffer
, sizeof(szBuffer
), L
"\\ntuser.dat");
1078 /* Acquire restore privilege */
1079 if (!AcquireRemoveRestorePrivilege(TRUE
))
1081 Error
= GetLastError();
1082 DPRINT1("Error: %lu\n", Error
);
1087 /* Load the user hive */
1088 Error
= RegLoadKeyW(HKEY_USERS
,
1091 AcquireRemoveRestorePrivilege(FALSE
);
1092 if (Error
!= ERROR_SUCCESS
)
1094 DPRINT1("Error: %lu\n", Error
);
1099 /* Initialize user hive */
1100 if (!CreateUserHive(SidString
, szUserProfilePath
))
1102 Error
= GetLastError();
1103 DPRINT1("Error: %lu\n", Error
);
1107 /* Unload the hive */
1108 AcquireRemoveRestorePrivilege(TRUE
);
1109 RegUnLoadKeyW(HKEY_USERS
, SidString
);
1110 AcquireRemoveRestorePrivilege(FALSE
);
1113 * If the caller wants to retrieve the user profile path,
1114 * give it now. 'dwDirSize' is the number of characters.
1116 if (lpProfileDir
&& dwDirSize
)
1117 StringCchCopyW(lpProfileDir
, dwDirSize
, szUserProfilePath
);
1120 LocalFree((HLOCAL
)SidString
);
1121 SetLastError((DWORD
)Error
);
1123 DPRINT("CreateUserProfileExW() done\n");
1132 _In_ LPCSTR lpSidString
,
1133 _In_opt_ LPCSTR lpProfilePath
,
1134 _In_opt_ LPCSTR lpComputerName
)
1137 UNICODE_STRING SidString
= {0, 0, NULL
}, ProfilePath
= {0, 0, NULL
}, ComputerName
= {0, 0, NULL
};
1139 DPRINT("DeleteProfileA() called\n");
1141 /* Conversion to UNICODE */
1143 RtlCreateUnicodeStringFromAsciiz(&SidString
,
1144 (LPSTR
)lpSidString
);
1147 RtlCreateUnicodeStringFromAsciiz(&ProfilePath
,
1148 (LPSTR
)lpProfilePath
);
1151 RtlCreateUnicodeStringFromAsciiz(&ComputerName
,
1152 (LPSTR
)lpComputerName
);
1154 /* Call the UNICODE function */
1155 bResult
= DeleteProfileW(SidString
.Buffer
,
1157 ComputerName
.Buffer
);
1159 /* Memory cleanup */
1161 RtlFreeUnicodeString(&SidString
);
1164 RtlFreeUnicodeString(&ProfilePath
);
1167 RtlFreeUnicodeString(&ComputerName
);
1176 _In_ LPCWSTR lpSidString
,
1177 _In_opt_ LPCWSTR lpProfilePath
,
1178 _In_opt_ LPCWSTR lpComputerName
)
1180 HKEY hProfilesKey
= NULL
, hProfileKey
= NULL
;
1181 WCHAR szRawProfilePath
[MAX_PATH
], szProfilePath
[MAX_PATH
];
1182 DWORD dwLength
, dwType
;
1183 DWORD dwError
= ERROR_SUCCESS
;
1186 DPRINT("DeleteProfileW(%S %S %S)\n", lpSidString
, lpProfilePath
, lpComputerName
);
1188 if (lpSidString
== NULL
)
1190 SetLastError(ERROR_INVALID_PARAMETER
);
1194 if (lpProfilePath
!= NULL
)
1196 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1197 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1201 if (dwError
!= ERROR_SUCCESS
)
1203 DPRINT1("Error: %lu\n", dwError
);
1207 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1212 if (dwError
!= ERROR_SUCCESS
)
1214 DPRINT1("Error: %lu\n", dwError
);
1218 /* Get the profile image path */
1219 dwLength
= sizeof(szRawProfilePath
);
1220 dwError
= RegQueryValueExW(hProfileKey
,
1221 L
"ProfileImagePath",
1224 (PBYTE
)szRawProfilePath
,
1226 if (dwError
!= ERROR_SUCCESS
)
1228 DPRINT1("Error: %lu\n", dwError
);
1232 if (!ExpandEnvironmentStringsW(szRawProfilePath
,
1234 ARRAYSIZE(szProfilePath
)))
1236 dwError
= GetLastError();
1237 DPRINT1("Failled to expand the raw profile path (Error %lu)\n", dwError
);
1243 StringCchCopyW(szProfilePath
, ARRAYSIZE(szProfilePath
), lpProfilePath
);
1246 DPRINT("ProfilePath: %S\n", szProfilePath
);
1248 if (!RemoveDirectoryPath(szProfilePath
))
1250 dwError
= GetLastError();
1251 DPRINT1("Error: %lu\n", dwError
);
1258 if (hProfileKey
!= NULL
)
1259 RegCloseKey(hProfileKey
);
1261 if (hProfilesKey
!= NULL
)
1262 RegCloseKey(hProfilesKey
);
1270 GetAllUsersProfileDirectoryA(
1271 _Out_opt_ LPSTR lpProfileDir
,
1272 _Inout_ LPDWORD lpcchSize
)
1279 SetLastError(ERROR_INVALID_PARAMETER
);
1283 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1284 *lpcchSize
* sizeof(WCHAR
));
1285 if (lpBuffer
== NULL
)
1288 bResult
= GetAllUsersProfileDirectoryW(lpBuffer
,
1290 if (bResult
&& lpProfileDir
)
1292 bResult
= WideCharToMultiByte(CP_ACP
,
1302 GlobalFree(lpBuffer
);
1310 GetAllUsersProfileDirectoryW(
1311 _Out_opt_ LPWSTR lpProfileDir
,
1312 _Inout_ LPDWORD lpcchSize
)
1314 WCHAR szProfilePath
[MAX_PATH
];
1315 WCHAR szBuffer
[MAX_PATH
];
1316 DWORD dwType
, dwLength
;
1322 SetLastError(ERROR_INVALID_PARAMETER
);
1326 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1327 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1331 if (Error
!= ERROR_SUCCESS
)
1333 DPRINT1("Error: %lu\n", Error
);
1334 SetLastError((DWORD
)Error
);
1338 /* Get profiles path */
1339 dwLength
= sizeof(szBuffer
);
1340 Error
= RegQueryValueExW(hKey
,
1341 L
"ProfilesDirectory",
1346 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1348 DPRINT1("Error: %lu\n", Error
);
1350 SetLastError((DWORD
)Error
);
1355 if (!ExpandEnvironmentStringsW(szBuffer
,
1357 ARRAYSIZE(szProfilePath
)))
1359 DPRINT1("Error: %lu\n", GetLastError());
1364 /* Get 'AllUsersProfile' name */
1365 dwLength
= sizeof(szBuffer
);
1366 Error
= RegQueryValueExW(hKey
,
1372 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1374 DPRINT1("Error: %lu\n", Error
);
1376 SetLastError((DWORD
)Error
);
1382 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), L
"\\");
1383 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), szBuffer
);
1385 dwLength
= wcslen(szProfilePath
) + 1;
1386 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1388 StringCchCopyW(lpProfileDir
, *lpcchSize
, szProfilePath
);
1389 *lpcchSize
= dwLength
;
1392 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1394 *lpcchSize
= dwLength
;
1395 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1403 GetDefaultUserProfileDirectoryA(
1404 _Out_opt_ LPSTR lpProfileDir
,
1405 _Inout_ LPDWORD lpcchSize
)
1412 SetLastError(ERROR_INVALID_PARAMETER
);
1416 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1417 *lpcchSize
* sizeof(WCHAR
));
1418 if (lpBuffer
== NULL
)
1421 bResult
= GetDefaultUserProfileDirectoryW(lpBuffer
,
1423 if (bResult
&& lpProfileDir
)
1425 bResult
= WideCharToMultiByte(CP_ACP
,
1435 GlobalFree(lpBuffer
);
1443 GetDefaultUserProfileDirectoryW(
1444 _Out_opt_ LPWSTR lpProfileDir
,
1445 _Inout_ LPDWORD lpcchSize
)
1447 WCHAR szProfilePath
[MAX_PATH
];
1448 WCHAR szBuffer
[MAX_PATH
];
1449 DWORD dwType
, dwLength
;
1455 SetLastError(ERROR_INVALID_PARAMETER
);
1459 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1460 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1464 if (Error
!= ERROR_SUCCESS
)
1466 DPRINT1("Error: %lu\n", Error
);
1467 SetLastError((DWORD
)Error
);
1471 /* Get profiles path */
1472 dwLength
= sizeof(szBuffer
);
1473 Error
= RegQueryValueExW(hKey
,
1474 L
"ProfilesDirectory",
1479 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1481 DPRINT1("Error: %lu\n", Error
);
1483 SetLastError((DWORD
)Error
);
1488 if (!ExpandEnvironmentStringsW(szBuffer
,
1490 ARRAYSIZE(szProfilePath
)))
1492 DPRINT1("Error: %lu\n", GetLastError());
1497 /* Get 'DefaultUserProfile' name */
1498 dwLength
= sizeof(szBuffer
);
1499 Error
= RegQueryValueExW(hKey
,
1500 L
"DefaultUserProfile",
1505 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1507 DPRINT1("Error: %lu\n", Error
);
1509 SetLastError((DWORD
)Error
);
1515 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), L
"\\");
1516 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), szBuffer
);
1518 dwLength
= wcslen(szProfilePath
) + 1;
1519 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1521 StringCchCopyW(lpProfileDir
, *lpcchSize
, szProfilePath
);
1522 *lpcchSize
= dwLength
;
1525 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1527 *lpcchSize
= dwLength
;
1528 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1536 GetProfilesDirectoryA(
1537 _Out_ LPSTR lpProfileDir
, // _Out_opt_
1538 _Inout_ LPDWORD lpcchSize
)
1543 if (!lpcchSize
|| !lpProfileDir
)
1545 SetLastError(ERROR_INVALID_PARAMETER
);
1549 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1550 *lpcchSize
* sizeof(WCHAR
));
1551 if (lpBuffer
== NULL
)
1554 bResult
= GetProfilesDirectoryW(lpBuffer
,
1556 if (bResult
&& lpProfileDir
)
1558 bResult
= WideCharToMultiByte(CP_ACP
,
1568 GlobalFree(lpBuffer
);
1576 GetProfilesDirectoryW(
1577 _Out_ LPWSTR lpProfilesDir
, // _Out_opt_
1578 _Inout_ LPDWORD lpcchSize
)
1580 WCHAR szProfilesPath
[MAX_PATH
];
1581 WCHAR szBuffer
[MAX_PATH
];
1582 DWORD dwType
, dwLength
;
1588 SetLastError(ERROR_INVALID_PARAMETER
);
1592 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1593 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1597 if (Error
!= ERROR_SUCCESS
)
1599 DPRINT1("Error: %lu\n", Error
);
1600 SetLastError((DWORD
)Error
);
1604 /* Get profiles path */
1605 dwLength
= sizeof(szBuffer
);
1606 Error
= RegQueryValueExW(hKey
,
1607 L
"ProfilesDirectory",
1612 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1614 DPRINT1("Error: %lu\n", Error
);
1616 SetLastError((DWORD
)Error
);
1623 if (!ExpandEnvironmentStringsW(szBuffer
,
1625 ARRAYSIZE(szProfilesPath
)))
1627 DPRINT1("Error: %lu\n", GetLastError());
1631 dwLength
= wcslen(szProfilesPath
) + 1;
1632 if (lpProfilesDir
&& (*lpcchSize
>= dwLength
))
1634 StringCchCopyW(lpProfilesDir
, *lpcchSize
, szProfilesPath
);
1635 *lpcchSize
= dwLength
;
1638 else // if (!lpProfilesDir || (*lpcchSize < dwLength))
1640 *lpcchSize
= dwLength
;
1641 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1650 _Out_ PDWORD pdwFlags
)
1652 UNICODE_STRING SidString
= {0, 0, NULL
};
1654 HKEY hProfilesKey
= NULL
, hProfileKey
= NULL
;
1655 DWORD dwType
, dwLength
, dwState
= 0;
1657 BOOL bResult
= FALSE
;
1659 DPRINT("GetProfileType(%p)\n", pdwFlags
);
1661 if (pdwFlags
== NULL
)
1663 SetLastError(ERROR_INVALID_PARAMETER
);
1667 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY
, TRUE
, &hToken
))
1669 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
1671 DPRINT1("Failed to open a token (Error %lu)\n", GetLastError());
1676 /* Get the user SID string */
1677 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1679 DPRINT1("GetUserSidStringFromToken() failed\n");
1683 DPRINT("SID: %wZ\n", &SidString
);
1685 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1686 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1690 if (dwError
!= ERROR_SUCCESS
)
1692 DPRINT1("Error: %lu\n", dwError
);
1693 SetLastError(dwError
);
1697 dwError
= RegOpenKeyExW(hProfilesKey
,
1700 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
1702 if (dwError
!= ERROR_SUCCESS
)
1704 DPRINT1("Error: %lu\n", dwError
);
1705 SetLastError(dwError
);
1709 /* Get the State value */
1710 dwLength
= sizeof(dwState
);
1711 dwError
= RegQueryValueExW(hProfileKey
,
1717 if (dwError
!= ERROR_SUCCESS
)
1719 DPRINT1("Error: %lu\n", dwError
);
1720 SetLastError(dwError
);
1726 if (dwState
& 0x80) /* PROFILE_GUEST_USER */
1727 *pdwFlags
|= PT_TEMPORARY
;
1729 /* FIXME: Add checks for PT_MANDATORY and PT_ROAMING */
1734 if (hProfileKey
!= NULL
)
1735 RegCloseKey(hProfileKey
);
1737 if (hProfilesKey
!= NULL
)
1738 RegCloseKey(hProfilesKey
);
1740 RtlFreeUnicodeString(&SidString
);
1742 CloseHandle(hToken
);
1750 GetUserProfileDirectoryA(
1752 _Out_opt_ LPSTR lpProfileDir
,
1753 _Inout_ LPDWORD lpcchSize
)
1758 if (!lpcchSize
|| !lpProfileDir
)
1760 SetLastError(ERROR_INVALID_PARAMETER
);
1764 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1765 *lpcchSize
* sizeof(WCHAR
));
1766 if (lpBuffer
== NULL
)
1769 bResult
= GetUserProfileDirectoryW(hToken
,
1772 if (bResult
&& lpProfileDir
)
1774 bResult
= WideCharToMultiByte(CP_ACP
,
1784 GlobalFree(lpBuffer
);
1792 GetUserProfileDirectoryW(
1794 _Out_opt_ LPWSTR lpProfileDir
,
1795 _Inout_ LPDWORD lpcchSize
)
1797 UNICODE_STRING SidString
;
1798 WCHAR szKeyName
[MAX_PATH
];
1799 WCHAR szRawImagePath
[MAX_PATH
];
1800 WCHAR szImagePath
[MAX_PATH
];
1801 DWORD dwType
, dwLength
;
1807 SetLastError(ERROR_INVALID_HANDLE
);
1813 SetLastError(ERROR_INVALID_PARAMETER
);
1817 /* Get the user SID string */
1818 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1820 DPRINT1("GetUserSidStringFromToken() failed\n");
1824 DPRINT("SidString: '%wZ'\n", &SidString
);
1826 StringCbCopyW(szKeyName
, sizeof(szKeyName
),
1827 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
1828 StringCbCatW(szKeyName
, sizeof(szKeyName
), SidString
.Buffer
);
1830 RtlFreeUnicodeString(&SidString
);
1832 DPRINT("KeyName: '%S'\n", szKeyName
);
1834 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1839 if (Error
!= ERROR_SUCCESS
)
1841 DPRINT1("Error: %lu\n", Error
);
1842 SetLastError((DWORD
)Error
);
1846 dwLength
= sizeof(szRawImagePath
);
1847 Error
= RegQueryValueExW(hKey
,
1848 L
"ProfileImagePath",
1851 (LPBYTE
)szRawImagePath
,
1853 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1855 DPRINT1("Error: %lu\n", Error
);
1857 SetLastError((DWORD
)Error
);
1863 DPRINT("RawImagePath: '%S'\n", szRawImagePath
);
1866 if (!ExpandEnvironmentStringsW(szRawImagePath
,
1868 ARRAYSIZE(szImagePath
)))
1870 DPRINT1("Error: %lu\n", GetLastError());
1874 DPRINT("ImagePath: '%S'\n", szImagePath
);
1876 dwLength
= wcslen(szImagePath
) + 1;
1877 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1879 StringCchCopyW(lpProfileDir
, *lpcchSize
, szImagePath
);
1880 *lpcchSize
= dwLength
;
1883 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1885 *lpcchSize
= dwLength
;
1886 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1896 _Inout_ LPPROFILEINFOA lpProfileInfo
)
1898 BOOL bResult
= FALSE
;
1899 PROFILEINFOW ProfileInfoW
= {0};
1902 DPRINT("LoadUserProfileA() called\n");
1904 /* Check profile info */
1905 if (!lpProfileInfo
|| (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOA
)) ||
1906 (lpProfileInfo
->lpUserName
== NULL
) || (lpProfileInfo
->lpUserName
[0] == 0))
1908 SetLastError(ERROR_INVALID_PARAMETER
);
1912 /* Convert the structure to UNICODE... */
1913 ProfileInfoW
.dwSize
= sizeof(ProfileInfoW
);
1914 ProfileInfoW
.dwFlags
= lpProfileInfo
->dwFlags
;
1916 if (lpProfileInfo
->lpUserName
)
1918 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpUserName
, -1, NULL
, 0);
1919 ProfileInfoW
.lpUserName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1920 if (!ProfileInfoW
.lpUserName
)
1922 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1925 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpUserName
, -1, ProfileInfoW
.lpUserName
, len
);
1928 if (lpProfileInfo
->lpProfilePath
)
1930 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpProfilePath
, -1, NULL
, 0);
1931 ProfileInfoW
.lpProfilePath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1932 if (!ProfileInfoW
.lpProfilePath
)
1934 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1937 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpProfilePath
, -1, ProfileInfoW
.lpProfilePath
, len
);
1940 if (lpProfileInfo
->lpDefaultPath
)
1942 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpDefaultPath
, -1, NULL
, 0);
1943 ProfileInfoW
.lpDefaultPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1944 if (!ProfileInfoW
.lpDefaultPath
)
1946 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1949 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpDefaultPath
, -1, ProfileInfoW
.lpDefaultPath
, len
);
1952 if (lpProfileInfo
->lpServerName
)
1954 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpServerName
, -1, NULL
, 0);
1955 ProfileInfoW
.lpServerName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1956 if (!ProfileInfoW
.lpServerName
)
1958 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1961 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpServerName
, -1, ProfileInfoW
.lpServerName
, len
);
1964 if ((ProfileInfoW
.dwFlags
& PI_APPLYPOLICY
) != 0 && lpProfileInfo
->lpPolicyPath
)
1966 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpPolicyPath
, -1, NULL
, 0);
1967 ProfileInfoW
.lpPolicyPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1968 if (!ProfileInfoW
.lpPolicyPath
)
1970 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1973 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpPolicyPath
, -1, ProfileInfoW
.lpPolicyPath
, len
);
1976 /* ... and call the UNICODE function */
1977 bResult
= LoadUserProfileW(hToken
, &ProfileInfoW
);
1979 /* Save the returned value */
1980 lpProfileInfo
->hProfile
= ProfileInfoW
.hProfile
;
1983 /* Memory cleanup */
1984 if (ProfileInfoW
.lpUserName
)
1985 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpUserName
);
1987 if (ProfileInfoW
.lpProfilePath
)
1988 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpProfilePath
);
1990 if (ProfileInfoW
.lpDefaultPath
)
1991 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpDefaultPath
);
1993 if (ProfileInfoW
.lpServerName
)
1994 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpServerName
);
1996 if ((ProfileInfoW
.dwFlags
& PI_APPLYPOLICY
) != 0 && ProfileInfoW
.lpPolicyPath
)
1997 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpPolicyPath
);
2007 _Inout_ LPPROFILEINFOW lpProfileInfo
)
2009 WCHAR szUserHivePath
[MAX_PATH
];
2010 PTOKEN_USER UserSid
= NULL
;
2011 UNICODE_STRING SidString
= { 0, 0, NULL
};
2012 HANDLE hProfileMutex
= NULL
;
2015 DWORD dwLength
= sizeof(szUserHivePath
) / sizeof(szUserHivePath
[0]);
2017 DPRINT("LoadUserProfileW(%p %p)\n", hToken
, lpProfileInfo
);
2019 /* Check profile info */
2020 if (!lpProfileInfo
|| (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOW
)) ||
2021 (lpProfileInfo
->lpUserName
== NULL
) || (lpProfileInfo
->lpUserName
[0] == 0))
2023 SetLastError(ERROR_INVALID_PARAMETER
);
2027 DPRINT("UserName: %S\n", lpProfileInfo
->lpUserName
);
2029 /* Get the user SID string */
2030 ret
= GetUserSidStringFromToken(hToken
, &SidString
);
2033 DPRINT1("GetUserSidStringFromToken() failed\n");
2038 /* Create the profile mutex */
2039 hProfileMutex
= CreateProfileMutex(SidString
.Buffer
);
2040 if (hProfileMutex
== NULL
)
2042 DPRINT1("Failed to create the profile mutex\n");
2046 /* Wait for the profile mutex */
2047 WaitForSingleObject(hProfileMutex
, INFINITE
);
2049 /* Don't load a profile twice */
2050 if (CheckForLoadedProfile(hToken
))
2052 DPRINT1("Profile %S already loaded\n", SidString
.Buffer
);
2056 DPRINT1("Loading profile %S\n", SidString
.Buffer
);
2058 if (lpProfileInfo
->lpProfilePath
)
2060 /* Use the caller's specified roaming user profile path */
2061 StringCbCopyW(szUserHivePath
, sizeof(szUserHivePath
), lpProfileInfo
->lpProfilePath
);
2065 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
2066 if (!GetProfilesDirectoryW(szUserHivePath
, &dwLength
))
2068 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
2073 /* Create user hive name */
2074 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\");
2075 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), lpProfileInfo
->lpUserName
);
2076 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\ntuser.dat");
2077 DPRINT("szUserHivePath: %S\n", szUserHivePath
);
2079 /* Create user profile directory if needed */
2080 if (GetFileAttributesW(szUserHivePath
) == INVALID_FILE_ATTRIBUTES
)
2083 if (GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &dwLength
) ||
2084 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
2086 DPRINT1 ("GetTokenInformation() failed\n");
2090 UserSid
= (PTOKEN_USER
)HeapAlloc(GetProcessHeap(), 0, dwLength
);
2093 DPRINT1("HeapAlloc() failed\n");
2094 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2098 if (!GetTokenInformation(hToken
, TokenUser
, UserSid
, dwLength
, &dwLength
))
2100 DPRINT1("GetTokenInformation() failed\n");
2104 /* Create profile */
2105 ret
= CreateUserProfileW(UserSid
->User
.Sid
, lpProfileInfo
->lpUserName
);
2108 DPRINT1("CreateUserProfileW() failed\n");
2113 /* Acquire restore privilege */
2114 if (!AcquireRemoveRestorePrivilege(TRUE
))
2116 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
2120 /* Load user registry hive */
2121 Error
= RegLoadKeyW(HKEY_USERS
,
2124 AcquireRemoveRestorePrivilege(FALSE
);
2126 /* HACK: Do not fail if the profile has already been loaded! */
2127 if (Error
== ERROR_SHARING_VIOLATION
)
2128 Error
= ERROR_SUCCESS
;
2130 if (Error
!= ERROR_SUCCESS
)
2132 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error
);
2133 SetLastError((DWORD
)Error
);
2137 SetProfileData(SidString
.Buffer
,
2138 lpProfileInfo
->dwFlags
,
2142 /* Open future HKEY_CURRENT_USER */
2143 Error
= RegOpenKeyExW(HKEY_USERS
,
2147 (PHKEY
)&lpProfileInfo
->hProfile
);
2148 if (Error
!= ERROR_SUCCESS
)
2150 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error
);
2151 SetLastError((DWORD
)Error
);
2155 Error
= IncrementRefCount(SidString
.Buffer
, NULL
);
2156 if (Error
!= ERROR_SUCCESS
)
2158 DPRINT1("IncrementRefCount() failed (Error %ld)\n", Error
);
2159 SetLastError((DWORD
)Error
);
2166 if (UserSid
!= NULL
)
2167 HeapFree(GetProcessHeap(), 0, UserSid
);
2169 if (hProfileMutex
!= NULL
)
2171 ReleaseMutex(hProfileMutex
);
2172 CloseHandle(hProfileMutex
);
2175 RtlFreeUnicodeString(&SidString
);
2177 DPRINT("LoadUserProfileW() done\n");
2186 _In_ HANDLE hProfile
)
2188 UNICODE_STRING SidString
= {0, 0, NULL
};
2189 HANDLE hProfileMutex
= NULL
;
2190 HKEY hProfilesKey
= NULL
, hProfileKey
= NULL
;
2191 DWORD dwRefCount
= 0, dwLength
, dwType
, dwState
= 0;
2195 DPRINT("UnloadUserProfile() called\n");
2197 if (hProfile
== NULL
)
2199 DPRINT1("Invalid profile handle\n");
2200 SetLastError(ERROR_INVALID_PARAMETER
);
2204 /* Get the user SID string */
2205 if (!GetUserSidStringFromToken(hToken
, &SidString
))
2207 DPRINT1("GetUserSidStringFromToken() failed\n");
2211 DPRINT("SidString: '%wZ'\n", &SidString
);
2213 /* Create the profile mutex */
2214 hProfileMutex
= CreateProfileMutex(SidString
.Buffer
);
2215 if (hProfileMutex
== NULL
)
2217 DPRINT1("Failed to create the profile mutex\n");
2221 /* Wait for the profile mutex */
2222 WaitForSingleObject(hProfileMutex
, INFINITE
);
2224 /* Close the profile handle */
2225 RegFlushKey(hProfile
);
2226 RegCloseKey(hProfile
);
2228 dwError
= DecrementRefCount(SidString
.Buffer
, &dwRefCount
);
2229 if (dwError
!= ERROR_SUCCESS
)
2231 DPRINT1("DecrementRefCount() failed (Error %lu)\n", dwError
);
2232 SetLastError(dwError
);
2236 if (dwRefCount
== 0)
2238 DPRINT("RefCount is 0: Unload the Hive!\n");
2240 /* Acquire restore privilege */
2241 if (!AcquireRemoveRestorePrivilege(TRUE
))
2243 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %lu)\n", GetLastError());
2251 dwError
= RegOpenKeyExW(HKEY_USERS
,
2256 if (dwError
== ERROR_SUCCESS
)
2258 RegDeleteKeyW(hUserKey
,
2259 L
"Volatile Environment");
2261 RegCloseKey(hUserKey
);
2266 /* Unload the hive */
2267 dwError
= RegUnLoadKeyW(HKEY_USERS
,
2270 /* Remove restore privilege */
2271 AcquireRemoveRestorePrivilege(FALSE
);
2273 if (dwError
!= ERROR_SUCCESS
)
2275 DPRINT1("RegUnLoadKeyW() failed (Error %lu)\n", dwError
);
2276 SetLastError(dwError
);
2280 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2281 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
2285 if (dwError
!= ERROR_SUCCESS
)
2287 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError
);
2288 SetLastError(dwError
);
2292 dwError
= RegOpenKeyExW(hProfilesKey
,
2297 if (dwError
!= ERROR_SUCCESS
)
2299 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError
);
2300 SetLastError(dwError
);
2304 /* Get the State value */
2305 dwLength
= sizeof(dwState
);
2306 dwError
= RegQueryValueExW(hProfileKey
,
2312 if (dwError
!= ERROR_SUCCESS
)
2314 DPRINT1("RegQueryValueExW() failed (Error %lu)\n", dwError
);
2315 SetLastError(dwError
);
2319 /* Delete a guest profile */
2320 if (dwState
& 0x80) // PROFILE_GUEST_USER
2322 if (!DeleteProfileW(SidString
.Buffer
, NULL
, NULL
))
2324 DPRINT1("DeleteProfile(%S, NULL, NULL) failed (Error %lu)\n",
2325 SidString
.Buffer
, GetLastError());
2334 if (hProfileKey
!= NULL
)
2335 RegCloseKey(hProfileKey
);
2337 if (hProfilesKey
!= NULL
)
2338 RegCloseKey(hProfilesKey
);
2340 if (hProfileMutex
!= NULL
)
2342 ReleaseMutex(hProfileMutex
);
2343 CloseHandle(hProfileMutex
);
2346 RtlFreeUnicodeString(&SidString
);
2348 DPRINT("UnloadUserProfile() done\n");