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 DPRINT1("DeleteProfileW(%S %S %S) not implemented!\n", lpSidString
, lpProfilePath
, lpComputerName
);
1181 return TRUE
; //FALSE;
1187 GetAllUsersProfileDirectoryA(
1188 _Out_opt_ LPSTR lpProfileDir
,
1189 _Inout_ LPDWORD lpcchSize
)
1196 SetLastError(ERROR_INVALID_PARAMETER
);
1200 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1201 *lpcchSize
* sizeof(WCHAR
));
1202 if (lpBuffer
== NULL
)
1205 bResult
= GetAllUsersProfileDirectoryW(lpBuffer
,
1207 if (bResult
&& lpProfileDir
)
1209 bResult
= WideCharToMultiByte(CP_ACP
,
1219 GlobalFree(lpBuffer
);
1227 GetAllUsersProfileDirectoryW(
1228 _Out_opt_ LPWSTR lpProfileDir
,
1229 _Inout_ LPDWORD lpcchSize
)
1231 WCHAR szProfilePath
[MAX_PATH
];
1232 WCHAR szBuffer
[MAX_PATH
];
1233 DWORD dwType
, dwLength
;
1239 SetLastError(ERROR_INVALID_PARAMETER
);
1243 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1244 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1248 if (Error
!= ERROR_SUCCESS
)
1250 DPRINT1("Error: %lu\n", Error
);
1251 SetLastError((DWORD
)Error
);
1255 /* Get profiles path */
1256 dwLength
= sizeof(szBuffer
);
1257 Error
= RegQueryValueExW(hKey
,
1258 L
"ProfilesDirectory",
1263 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1265 DPRINT1("Error: %lu\n", Error
);
1267 SetLastError((DWORD
)Error
);
1272 if (!ExpandEnvironmentStringsW(szBuffer
,
1274 ARRAYSIZE(szProfilePath
)))
1276 DPRINT1("Error: %lu\n", GetLastError());
1281 /* Get 'AllUsersProfile' name */
1282 dwLength
= sizeof(szBuffer
);
1283 Error
= RegQueryValueExW(hKey
,
1289 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1291 DPRINT1("Error: %lu\n", Error
);
1293 SetLastError((DWORD
)Error
);
1299 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), L
"\\");
1300 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), szBuffer
);
1302 dwLength
= wcslen(szProfilePath
) + 1;
1303 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1305 StringCchCopyW(lpProfileDir
, *lpcchSize
, szProfilePath
);
1306 *lpcchSize
= dwLength
;
1309 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1311 *lpcchSize
= dwLength
;
1312 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1320 GetDefaultUserProfileDirectoryA(
1321 _Out_opt_ LPSTR lpProfileDir
,
1322 _Inout_ LPDWORD lpcchSize
)
1329 SetLastError(ERROR_INVALID_PARAMETER
);
1333 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1334 *lpcchSize
* sizeof(WCHAR
));
1335 if (lpBuffer
== NULL
)
1338 bResult
= GetDefaultUserProfileDirectoryW(lpBuffer
,
1340 if (bResult
&& lpProfileDir
)
1342 bResult
= WideCharToMultiByte(CP_ACP
,
1352 GlobalFree(lpBuffer
);
1360 GetDefaultUserProfileDirectoryW(
1361 _Out_opt_ LPWSTR lpProfileDir
,
1362 _Inout_ LPDWORD lpcchSize
)
1364 WCHAR szProfilePath
[MAX_PATH
];
1365 WCHAR szBuffer
[MAX_PATH
];
1366 DWORD dwType
, dwLength
;
1372 SetLastError(ERROR_INVALID_PARAMETER
);
1376 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1377 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1381 if (Error
!= ERROR_SUCCESS
)
1383 DPRINT1("Error: %lu\n", Error
);
1384 SetLastError((DWORD
)Error
);
1388 /* Get profiles path */
1389 dwLength
= sizeof(szBuffer
);
1390 Error
= RegQueryValueExW(hKey
,
1391 L
"ProfilesDirectory",
1396 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1398 DPRINT1("Error: %lu\n", Error
);
1400 SetLastError((DWORD
)Error
);
1405 if (!ExpandEnvironmentStringsW(szBuffer
,
1407 ARRAYSIZE(szProfilePath
)))
1409 DPRINT1("Error: %lu\n", GetLastError());
1414 /* Get 'DefaultUserProfile' name */
1415 dwLength
= sizeof(szBuffer
);
1416 Error
= RegQueryValueExW(hKey
,
1417 L
"DefaultUserProfile",
1422 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1424 DPRINT1("Error: %lu\n", Error
);
1426 SetLastError((DWORD
)Error
);
1432 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), L
"\\");
1433 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), szBuffer
);
1435 dwLength
= wcslen(szProfilePath
) + 1;
1436 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1438 StringCchCopyW(lpProfileDir
, *lpcchSize
, szProfilePath
);
1439 *lpcchSize
= dwLength
;
1442 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1444 *lpcchSize
= dwLength
;
1445 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1453 GetProfilesDirectoryA(
1454 _Out_ LPSTR lpProfileDir
, // _Out_opt_
1455 _Inout_ LPDWORD lpcchSize
)
1460 if (!lpcchSize
|| !lpProfileDir
)
1462 SetLastError(ERROR_INVALID_PARAMETER
);
1466 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1467 *lpcchSize
* sizeof(WCHAR
));
1468 if (lpBuffer
== NULL
)
1471 bResult
= GetProfilesDirectoryW(lpBuffer
,
1473 if (bResult
&& lpProfileDir
)
1475 bResult
= WideCharToMultiByte(CP_ACP
,
1485 GlobalFree(lpBuffer
);
1493 GetProfilesDirectoryW(
1494 _Out_ LPWSTR lpProfilesDir
, // _Out_opt_
1495 _Inout_ LPDWORD lpcchSize
)
1497 WCHAR szProfilesPath
[MAX_PATH
];
1498 WCHAR szBuffer
[MAX_PATH
];
1499 DWORD dwType
, dwLength
;
1505 SetLastError(ERROR_INVALID_PARAMETER
);
1509 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1510 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1514 if (Error
!= ERROR_SUCCESS
)
1516 DPRINT1("Error: %lu\n", Error
);
1517 SetLastError((DWORD
)Error
);
1521 /* Get profiles path */
1522 dwLength
= sizeof(szBuffer
);
1523 Error
= RegQueryValueExW(hKey
,
1524 L
"ProfilesDirectory",
1529 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1531 DPRINT1("Error: %lu\n", Error
);
1533 SetLastError((DWORD
)Error
);
1540 if (!ExpandEnvironmentStringsW(szBuffer
,
1542 ARRAYSIZE(szProfilesPath
)))
1544 DPRINT1("Error: %lu\n", GetLastError());
1548 dwLength
= wcslen(szProfilesPath
) + 1;
1549 if (lpProfilesDir
&& (*lpcchSize
>= dwLength
))
1551 StringCchCopyW(lpProfilesDir
, *lpcchSize
, szProfilesPath
);
1552 *lpcchSize
= dwLength
;
1555 else // if (!lpProfilesDir || (*lpcchSize < dwLength))
1557 *lpcchSize
= dwLength
;
1558 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1567 _Out_ PDWORD pdwFlags
)
1569 UNICODE_STRING SidString
= {0, 0, NULL
};
1571 HKEY hProfilesKey
= NULL
, hProfileKey
= NULL
;
1572 DWORD dwType
, dwLength
, dwState
= 0;
1574 BOOL bResult
= FALSE
;
1576 DPRINT("GetProfileType(%p)\n", pdwFlags
);
1578 if (pdwFlags
== NULL
)
1580 SetLastError(ERROR_INVALID_PARAMETER
);
1584 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY
, TRUE
, &hToken
))
1586 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
1588 DPRINT1("Failed to open a token (Error %lu)\n", GetLastError());
1593 /* Get the user SID string */
1594 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1596 DPRINT1("GetUserSidStringFromToken() failed\n");
1600 DPRINT("SID: %wZ\n", &SidString
);
1602 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1603 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1607 if (dwError
!= ERROR_SUCCESS
)
1609 DPRINT1("Error: %lu\n", dwError
);
1610 SetLastError(dwError
);
1614 dwError
= RegOpenKeyExW(hProfilesKey
,
1617 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
1619 if (dwError
!= ERROR_SUCCESS
)
1621 DPRINT1("Error: %lu\n", dwError
);
1622 SetLastError(dwError
);
1626 /* Get the State value */
1627 dwLength
= sizeof(dwState
);
1628 dwError
= RegQueryValueExW(hProfileKey
,
1634 if (dwError
!= ERROR_SUCCESS
)
1636 DPRINT1("Error: %lu\n", dwError
);
1637 SetLastError(dwError
);
1643 if (dwState
& 0x80) /* PROFILE_GUEST_USER */
1644 *pdwFlags
|= PT_TEMPORARY
;
1646 /* FIXME: Add checks for PT_MANDATORY and PT_ROAMING */
1651 if (hProfileKey
!= NULL
)
1652 RegCloseKey(hProfileKey
);
1654 if (hProfilesKey
!= NULL
)
1655 RegCloseKey(hProfilesKey
);
1657 RtlFreeUnicodeString(&SidString
);
1659 CloseHandle(hToken
);
1667 GetUserProfileDirectoryA(
1669 _Out_opt_ LPSTR lpProfileDir
,
1670 _Inout_ LPDWORD lpcchSize
)
1675 if (!lpcchSize
|| !lpProfileDir
)
1677 SetLastError(ERROR_INVALID_PARAMETER
);
1681 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1682 *lpcchSize
* sizeof(WCHAR
));
1683 if (lpBuffer
== NULL
)
1686 bResult
= GetUserProfileDirectoryW(hToken
,
1689 if (bResult
&& lpProfileDir
)
1691 bResult
= WideCharToMultiByte(CP_ACP
,
1701 GlobalFree(lpBuffer
);
1709 GetUserProfileDirectoryW(
1711 _Out_opt_ LPWSTR lpProfileDir
,
1712 _Inout_ LPDWORD lpcchSize
)
1714 UNICODE_STRING SidString
;
1715 WCHAR szKeyName
[MAX_PATH
];
1716 WCHAR szRawImagePath
[MAX_PATH
];
1717 WCHAR szImagePath
[MAX_PATH
];
1718 DWORD dwType
, dwLength
;
1724 SetLastError(ERROR_INVALID_HANDLE
);
1730 SetLastError(ERROR_INVALID_PARAMETER
);
1734 /* Get the user SID string */
1735 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1737 DPRINT1("GetUserSidStringFromToken() failed\n");
1741 DPRINT("SidString: '%wZ'\n", &SidString
);
1743 StringCbCopyW(szKeyName
, sizeof(szKeyName
),
1744 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
1745 StringCbCatW(szKeyName
, sizeof(szKeyName
), SidString
.Buffer
);
1747 RtlFreeUnicodeString(&SidString
);
1749 DPRINT("KeyName: '%S'\n", szKeyName
);
1751 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1756 if (Error
!= ERROR_SUCCESS
)
1758 DPRINT1("Error: %lu\n", Error
);
1759 SetLastError((DWORD
)Error
);
1763 dwLength
= sizeof(szRawImagePath
);
1764 Error
= RegQueryValueExW(hKey
,
1765 L
"ProfileImagePath",
1768 (LPBYTE
)szRawImagePath
,
1770 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1772 DPRINT1("Error: %lu\n", Error
);
1774 SetLastError((DWORD
)Error
);
1780 DPRINT("RawImagePath: '%S'\n", szRawImagePath
);
1783 if (!ExpandEnvironmentStringsW(szRawImagePath
,
1785 ARRAYSIZE(szImagePath
)))
1787 DPRINT1("Error: %lu\n", GetLastError());
1791 DPRINT("ImagePath: '%S'\n", szImagePath
);
1793 dwLength
= wcslen(szImagePath
) + 1;
1794 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1796 StringCchCopyW(lpProfileDir
, *lpcchSize
, szImagePath
);
1797 *lpcchSize
= dwLength
;
1800 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1802 *lpcchSize
= dwLength
;
1803 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1813 _Inout_ LPPROFILEINFOA lpProfileInfo
)
1815 BOOL bResult
= FALSE
;
1816 PROFILEINFOW ProfileInfoW
= {0};
1819 DPRINT("LoadUserProfileA() called\n");
1821 /* Check profile info */
1822 if (!lpProfileInfo
|| (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOA
)) ||
1823 (lpProfileInfo
->lpUserName
== NULL
) || (lpProfileInfo
->lpUserName
[0] == 0))
1825 SetLastError(ERROR_INVALID_PARAMETER
);
1829 /* Convert the structure to UNICODE... */
1830 ProfileInfoW
.dwSize
= sizeof(ProfileInfoW
);
1831 ProfileInfoW
.dwFlags
= lpProfileInfo
->dwFlags
;
1833 if (lpProfileInfo
->lpUserName
)
1835 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpUserName
, -1, NULL
, 0);
1836 ProfileInfoW
.lpUserName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1837 if (!ProfileInfoW
.lpUserName
)
1839 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1842 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpUserName
, -1, ProfileInfoW
.lpUserName
, len
);
1845 if (lpProfileInfo
->lpProfilePath
)
1847 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpProfilePath
, -1, NULL
, 0);
1848 ProfileInfoW
.lpProfilePath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1849 if (!ProfileInfoW
.lpProfilePath
)
1851 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1854 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpProfilePath
, -1, ProfileInfoW
.lpProfilePath
, len
);
1857 if (lpProfileInfo
->lpDefaultPath
)
1859 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpDefaultPath
, -1, NULL
, 0);
1860 ProfileInfoW
.lpDefaultPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1861 if (!ProfileInfoW
.lpDefaultPath
)
1863 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1866 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpDefaultPath
, -1, ProfileInfoW
.lpDefaultPath
, len
);
1869 if (lpProfileInfo
->lpServerName
)
1871 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpServerName
, -1, NULL
, 0);
1872 ProfileInfoW
.lpServerName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1873 if (!ProfileInfoW
.lpServerName
)
1875 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1878 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpServerName
, -1, ProfileInfoW
.lpServerName
, len
);
1881 if ((ProfileInfoW
.dwFlags
& PI_APPLYPOLICY
) != 0 && lpProfileInfo
->lpPolicyPath
)
1883 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpPolicyPath
, -1, NULL
, 0);
1884 ProfileInfoW
.lpPolicyPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1885 if (!ProfileInfoW
.lpPolicyPath
)
1887 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1890 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpPolicyPath
, -1, ProfileInfoW
.lpPolicyPath
, len
);
1893 /* ... and call the UNICODE function */
1894 bResult
= LoadUserProfileW(hToken
, &ProfileInfoW
);
1896 /* Save the returned value */
1897 lpProfileInfo
->hProfile
= ProfileInfoW
.hProfile
;
1900 /* Memory cleanup */
1901 if (ProfileInfoW
.lpUserName
)
1902 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpUserName
);
1904 if (ProfileInfoW
.lpProfilePath
)
1905 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpProfilePath
);
1907 if (ProfileInfoW
.lpDefaultPath
)
1908 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpDefaultPath
);
1910 if (ProfileInfoW
.lpServerName
)
1911 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpServerName
);
1913 if ((ProfileInfoW
.dwFlags
& PI_APPLYPOLICY
) != 0 && ProfileInfoW
.lpPolicyPath
)
1914 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpPolicyPath
);
1924 _Inout_ LPPROFILEINFOW lpProfileInfo
)
1926 WCHAR szUserHivePath
[MAX_PATH
];
1927 PTOKEN_USER UserSid
= NULL
;
1928 UNICODE_STRING SidString
= { 0, 0, NULL
};
1929 HANDLE hProfileMutex
= NULL
;
1932 DWORD dwLength
= sizeof(szUserHivePath
) / sizeof(szUserHivePath
[0]);
1934 DPRINT("LoadUserProfileW(%p %p)\n", hToken
, lpProfileInfo
);
1936 /* Check profile info */
1937 if (!lpProfileInfo
|| (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOW
)) ||
1938 (lpProfileInfo
->lpUserName
== NULL
) || (lpProfileInfo
->lpUserName
[0] == 0))
1940 SetLastError(ERROR_INVALID_PARAMETER
);
1944 DPRINT("UserName: %S\n", lpProfileInfo
->lpUserName
);
1946 /* Get the user SID string */
1947 ret
= GetUserSidStringFromToken(hToken
, &SidString
);
1950 DPRINT1("GetUserSidStringFromToken() failed\n");
1955 /* Create the profile mutex */
1956 hProfileMutex
= CreateProfileMutex(SidString
.Buffer
);
1957 if (hProfileMutex
== NULL
)
1959 DPRINT1("Failed to create the profile mutex\n");
1963 /* Wait for the profile mutex */
1964 WaitForSingleObject(hProfileMutex
, INFINITE
);
1966 /* Don't load a profile twice */
1967 if (CheckForLoadedProfile(hToken
))
1969 DPRINT1("Profile %S already loaded\n", SidString
.Buffer
);
1973 DPRINT1("Loading profile %S\n", SidString
.Buffer
);
1975 if (lpProfileInfo
->lpProfilePath
)
1977 /* Use the caller's specified roaming user profile path */
1978 StringCbCopyW(szUserHivePath
, sizeof(szUserHivePath
), lpProfileInfo
->lpProfilePath
);
1982 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
1983 if (!GetProfilesDirectoryW(szUserHivePath
, &dwLength
))
1985 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
1990 /* Create user hive name */
1991 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\");
1992 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), lpProfileInfo
->lpUserName
);
1993 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\ntuser.dat");
1994 DPRINT("szUserHivePath: %S\n", szUserHivePath
);
1996 /* Create user profile directory if needed */
1997 if (GetFileAttributesW(szUserHivePath
) == INVALID_FILE_ATTRIBUTES
)
2000 if (GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &dwLength
) ||
2001 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
2003 DPRINT1 ("GetTokenInformation() failed\n");
2007 UserSid
= (PTOKEN_USER
)HeapAlloc(GetProcessHeap(), 0, dwLength
);
2010 DPRINT1("HeapAlloc() failed\n");
2011 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2015 if (!GetTokenInformation(hToken
, TokenUser
, UserSid
, dwLength
, &dwLength
))
2017 DPRINT1("GetTokenInformation() failed\n");
2021 /* Create profile */
2022 ret
= CreateUserProfileW(UserSid
->User
.Sid
, lpProfileInfo
->lpUserName
);
2025 DPRINT1("CreateUserProfileW() failed\n");
2030 /* Acquire restore privilege */
2031 if (!AcquireRemoveRestorePrivilege(TRUE
))
2033 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
2037 /* Load user registry hive */
2038 Error
= RegLoadKeyW(HKEY_USERS
,
2041 AcquireRemoveRestorePrivilege(FALSE
);
2043 /* HACK: Do not fail if the profile has already been loaded! */
2044 if (Error
== ERROR_SHARING_VIOLATION
)
2045 Error
= ERROR_SUCCESS
;
2047 if (Error
!= ERROR_SUCCESS
)
2049 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error
);
2050 SetLastError((DWORD
)Error
);
2054 SetProfileData(SidString
.Buffer
,
2055 lpProfileInfo
->dwFlags
,
2059 /* Open future HKEY_CURRENT_USER */
2060 Error
= RegOpenKeyExW(HKEY_USERS
,
2064 (PHKEY
)&lpProfileInfo
->hProfile
);
2065 if (Error
!= ERROR_SUCCESS
)
2067 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error
);
2068 SetLastError((DWORD
)Error
);
2072 Error
= IncrementRefCount(SidString
.Buffer
, NULL
);
2073 if (Error
!= ERROR_SUCCESS
)
2075 DPRINT1("IncrementRefCount() failed (Error %ld)\n", Error
);
2076 SetLastError((DWORD
)Error
);
2083 if (UserSid
!= NULL
)
2084 HeapFree(GetProcessHeap(), 0, UserSid
);
2086 if (hProfileMutex
!= NULL
)
2088 ReleaseMutex(hProfileMutex
);
2089 CloseHandle(hProfileMutex
);
2092 RtlFreeUnicodeString(&SidString
);
2094 DPRINT("LoadUserProfileW() done\n");
2103 _In_ HANDLE hProfile
)
2105 UNICODE_STRING SidString
= {0, 0, NULL
};
2106 HANDLE hProfileMutex
= NULL
;
2107 HKEY hProfilesKey
= NULL
, hProfileKey
= NULL
;
2108 DWORD dwRefCount
= 0, dwLength
, dwType
, dwState
= 0;
2112 DPRINT("UnloadUserProfile() called\n");
2114 if (hProfile
== NULL
)
2116 DPRINT1("Invalid profile handle\n");
2117 SetLastError(ERROR_INVALID_PARAMETER
);
2121 /* Get the user SID string */
2122 if (!GetUserSidStringFromToken(hToken
, &SidString
))
2124 DPRINT1("GetUserSidStringFromToken() failed\n");
2128 DPRINT("SidString: '%wZ'\n", &SidString
);
2130 /* Create the profile mutex */
2131 hProfileMutex
= CreateProfileMutex(SidString
.Buffer
);
2132 if (hProfileMutex
== NULL
)
2134 DPRINT1("Failed to create the profile mutex\n");
2138 /* Wait for the profile mutex */
2139 WaitForSingleObject(hProfileMutex
, INFINITE
);
2141 /* Close the profile handle */
2142 RegFlushKey(hProfile
);
2143 RegCloseKey(hProfile
);
2145 dwError
= DecrementRefCount(SidString
.Buffer
, &dwRefCount
);
2146 if (dwError
!= ERROR_SUCCESS
)
2148 DPRINT1("DecrementRefCount() failed (Error %lu)\n", dwError
);
2149 SetLastError(dwError
);
2153 if (dwRefCount
== 0)
2155 DPRINT("RefCount is 0: Unload the Hive!\n");
2157 /* Acquire restore privilege */
2158 if (!AcquireRemoveRestorePrivilege(TRUE
))
2160 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %lu)\n", GetLastError());
2168 dwError
= RegOpenKeyExW(HKEY_USERS
,
2173 if (dwError
== ERROR_SUCCESS
)
2175 RegDeleteKeyW(hUserKey
,
2176 L
"Volatile Environment");
2178 RegCloseKey(hUserKey
);
2183 /* Unload the hive */
2184 dwError
= RegUnLoadKeyW(HKEY_USERS
,
2187 /* Remove restore privilege */
2188 AcquireRemoveRestorePrivilege(FALSE
);
2190 if (dwError
!= ERROR_SUCCESS
)
2192 DPRINT1("RegUnLoadKeyW() failed (Error %lu)\n", dwError
);
2193 SetLastError(dwError
);
2197 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2198 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
2202 if (dwError
!= ERROR_SUCCESS
)
2204 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError
);
2205 SetLastError(dwError
);
2209 dwError
= RegOpenKeyExW(hProfilesKey
,
2214 if (dwError
!= ERROR_SUCCESS
)
2216 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError
);
2217 SetLastError(dwError
);
2221 /* Get the State value */
2222 dwLength
= sizeof(dwState
);
2223 dwError
= RegQueryValueExW(hProfileKey
,
2229 if (dwError
!= ERROR_SUCCESS
)
2231 DPRINT1("RegQueryValueExW() failed (Error %lu)\n", dwError
);
2232 SetLastError(dwError
);
2236 /* Delete a guest profile */
2237 if (dwState
& 0x80) // PROFILE_GUEST_USER
2239 if (!DeleteProfileW(SidString
.Buffer
, NULL
, NULL
))
2241 DPRINT1("DeleteProfile(%S, NULL, NULL) failed (Error %lu)\n",
2242 SidString
.Buffer
, GetLastError());
2251 if (hProfileKey
!= NULL
)
2252 RegCloseKey(hProfileKey
);
2254 if (hProfilesKey
!= NULL
)
2255 RegCloseKey(hProfilesKey
);
2257 if (hProfileMutex
!= NULL
)
2259 ReleaseMutex(hProfileMutex
);
2260 CloseHandle(hProfileMutex
);
2263 RtlFreeUnicodeString(&SidString
);
2265 DPRINT("UnloadUserProfile() done\n");