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());
114 WCHAR szKeyName
[MAX_PATH
];
115 WCHAR szRawProfilePath
[MAX_PATH
];
116 WCHAR szProfilePath
[MAX_PATH
];
117 WCHAR szDefaultProfilePath
[MAX_PATH
];
118 UNICODE_STRING SidString
= {0, 0, NULL
};
119 HANDLE hToken
= NULL
;
120 PSID pUserSid
= NULL
;
121 HKEY hProfileKey
= NULL
;
123 BOOL bResult
= FALSE
;
127 DPRINT1("CopySystemProfile()\n");
129 if (!OpenProcessToken(GetCurrentProcess(),
130 TOKEN_QUERY
| TOKEN_IMPERSONATE
,
133 DPRINT1("Failed to open the process token (Error %lu)\n", GetLastError());
137 pUserSid
= GetUserSid(hToken
);
138 if (pUserSid
== NULL
)
140 DPRINT1("Failed to get the users SID (Error %lu)\n", GetLastError());
144 /* Get the user SID string */
145 if (!GetUserSidStringFromToken(hToken
, &SidString
))
147 DPRINT1("GetUserSidStringFromToken() failed\n");
151 StringCbCopyW(szKeyName
, sizeof(szKeyName
),
152 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
153 StringCbCatW(szKeyName
, sizeof(szKeyName
), SidString
.Buffer
);
155 RtlFreeUnicodeString(&SidString
);
157 dwError
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
164 if (dwError
!= ERROR_SUCCESS
)
166 DPRINT1("Failed to create the profile key for the %s profile (Error %lu)\n",
167 SidString
.Buffer
, dwError
);
171 dwError
= RegSetValueExW(hProfileKey
,
176 RtlLengthSid(pUserSid
));
177 if (dwError
!= ERROR_SUCCESS
)
179 DPRINT1("Failed to set the SID value (Error %lu)\n", dwError
);
183 wcscpy(szRawProfilePath
,
184 L
"%systemroot%\\system32\\config\\systemprofile");
186 dwError
= RegSetValueExW(hProfileKey
,
190 (PBYTE
)szRawProfilePath
,
191 (wcslen(szRawProfilePath
) + 1) * sizeof(WCHAR
));
192 if (dwError
!= ERROR_SUCCESS
)
194 DPRINT1("Failed to set the ProfileImagePath value (Error %lu)\n", dwError
);
198 /* Expand the raw profile path */
199 if (!ExpandEnvironmentStringsW(szRawProfilePath
,
201 ARRAYSIZE(szProfilePath
)))
203 DPRINT1("Failled to expand the raw profile path (Error %lu)\n", GetLastError());
207 /* Create the profile directory if it does not exist yet */
209 if (!CreateDirectoryW(szProfilePath
, NULL
))
211 if (GetLastError() != ERROR_ALREADY_EXISTS
)
213 DPRINT1("Failed to create the profile directory (Error %lu)\n", GetLastError());
218 /* Get the path of the default profile */
219 cchSize
= ARRAYSIZE(szDefaultProfilePath
);
220 if (!GetDefaultUserProfileDirectoryW(szDefaultProfilePath
, &cchSize
))
222 DPRINT1("Failed to create the default profile path (Error %lu)\n", GetLastError());
226 /* Copy the default profile into the new profile directory */
228 if (!CopyDirectory(szProfilePath
, szDefaultProfilePath
))
230 DPRINT1("Failed to copy the default profile directory (Error %lu)\n", GetLastError());
237 if (hProfileKey
!= NULL
)
238 RegCloseKey(hProfileKey
);
240 RtlFreeUnicodeString(&SidString
);
242 if (pUserSid
!= NULL
)
256 _In_ LPCSTR lpUserName
)
258 LPWSTR pUserNameW
= NULL
;
262 DPRINT("CreateUserProfileA(%p %s)\n", pSid
, lpUserName
);
264 /* Convert lpUserName to Unicode */
265 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, NULL
, 0);
266 pUserNameW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
267 if (pUserNameW
== NULL
)
269 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
272 MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, pUserNameW
, nLength
);
274 /* Call the Ex function */
275 bResult
= CreateUserProfileExW(pSid
,
282 HeapFree(GetProcessHeap(), 0, pUserNameW
);
292 _In_ LPCWSTR lpUserName
)
294 DPRINT("CreateUserProfileW(%p %S)\n", pSid
, lpUserName
);
296 /* Call the Ex function */
297 return CreateUserProfileExW(pSid
,
308 CreateUserProfileExA(
310 _In_ LPCSTR lpUserName
,
311 _In_opt_ LPCSTR lpUserHive
,
312 _Out_opt_ LPSTR lpProfileDir
,
313 _In_ DWORD dwDirSize
,
316 LPWSTR pUserNameW
= NULL
;
317 LPWSTR pUserHiveW
= NULL
;
318 LPWSTR pProfileDirW
= NULL
;
320 BOOL bResult
= FALSE
;
322 DPRINT("CreateUserProfileExA(%p %s %s %p %lu %d)\n",
323 pSid
, lpUserName
, lpUserHive
, lpProfileDir
, dwDirSize
, bWin9xUpg
);
325 /* Check the parameters */
326 if (lpProfileDir
!= NULL
&& dwDirSize
== 0)
328 SetLastError(ERROR_INVALID_PARAMETER
);
332 /* Convert lpUserName to Unicode */
333 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, NULL
, 0);
334 pUserNameW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
335 if (pUserNameW
== NULL
)
337 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
340 MultiByteToWideChar(CP_ACP
, 0, lpUserName
, -1, pUserNameW
, nLength
);
342 /* Convert lpUserHive to Unicode */
343 if (lpUserHive
!= NULL
)
345 nLength
= MultiByteToWideChar(CP_ACP
, 0, lpUserHive
, -1, NULL
, 0);
346 pUserHiveW
= HeapAlloc(GetProcessHeap(), 0, nLength
* sizeof(WCHAR
));
347 if (pUserHiveW
== NULL
)
349 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
352 MultiByteToWideChar(CP_ACP
, 0, lpUserHive
, -1, pUserHiveW
, nLength
);
355 /* Allocate a Unicode buffer for lpProfileDir */
356 if (lpProfileDir
!= NULL
)
358 pProfileDirW
= HeapAlloc(GetProcessHeap(), 0, dwDirSize
* sizeof(WCHAR
));
359 if (pProfileDirW
== NULL
)
361 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
366 /* Call the Unicode function */
367 bResult
= CreateUserProfileExW(pSid
,
374 /* Convert the profile path to ANSI */
375 if (bResult
&& lpProfileDir
!= NULL
)
377 WideCharToMultiByte(CP_ACP
, 0, pProfileDirW
, -1, lpProfileDir
, dwDirSize
, NULL
, NULL
);
381 /* Free the buffers */
382 if (pProfileDirW
!= NULL
)
383 HeapFree(GetProcessHeap(), 0, pProfileDirW
);
385 if (pUserHiveW
!= NULL
)
386 HeapFree(GetProcessHeap(), 0, pUserHiveW
);
388 if (pUserNameW
!= NULL
)
389 HeapFree(GetProcessHeap(), 0, pUserNameW
);
397 CreateUserProfileExW(
399 _In_ LPCWSTR lpUserName
,
400 _In_opt_ LPCWSTR lpUserHive
,
401 _Out_opt_ LPWSTR lpProfileDir
,
402 _In_ DWORD dwDirSize
,
405 WCHAR szRawProfilesPath
[MAX_PATH
];
406 WCHAR szProfilesPath
[MAX_PATH
];
407 WCHAR szUserProfilePath
[MAX_PATH
];
408 WCHAR szDefaultUserPath
[MAX_PATH
];
409 WCHAR szUserProfileName
[MAX_PATH
];
410 WCHAR szBuffer
[MAX_PATH
];
412 DWORD dwType
, dwLength
;
419 DPRINT("CreateUserProfileExW(%p %S %S %p %lu %d)\n",
420 pSid
, lpUserName
, lpUserHive
, lpProfileDir
, dwDirSize
, bWin9xUpg
);
422 /* Parameters validation */
423 if (!pSid
|| !lpUserName
)
425 SetLastError(ERROR_INVALID_PARAMETER
);
431 * - Add support for lpUserHive.
432 * - bWin9xUpg is obsolete. Don't waste your time implementing this.
435 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
436 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
440 if (Error
!= ERROR_SUCCESS
)
442 DPRINT1("Error: %lu\n", Error
);
443 SetLastError((DWORD
)Error
);
447 /* Get profiles path */
448 dwLength
= sizeof(szRawProfilesPath
);
449 Error
= RegQueryValueExW(hKey
,
450 L
"ProfilesDirectory",
453 (LPBYTE
)szRawProfilesPath
,
455 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
457 DPRINT1("Error: %lu\n", Error
);
459 SetLastError((DWORD
)Error
);
464 if (!ExpandEnvironmentStringsW(szRawProfilesPath
,
466 ARRAYSIZE(szProfilesPath
)))
468 DPRINT1("Error: %lu\n", GetLastError());
473 /* Create the profiles directory if it does not exist yet */
475 if (!CreateDirectoryW(szProfilesPath
, NULL
))
477 if (GetLastError() != ERROR_ALREADY_EXISTS
)
479 DPRINT1("Error: %lu\n", GetLastError());
484 /* Get default user path */
485 dwLength
= sizeof(szBuffer
);
486 Error
= RegQueryValueExW(hKey
,
487 L
"DefaultUserProfile",
492 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
494 DPRINT1("Error: %lu\n", Error
);
496 SetLastError((DWORD
)Error
);
502 StringCbCopyW(szUserProfileName
, sizeof(szUserProfileName
), lpUserName
);
504 /* Create user profile directory */
506 StringCbCopyW(szUserProfilePath
, sizeof(szUserProfilePath
), szProfilesPath
);
507 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), L
"\\");
508 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), szUserProfileName
);
511 if (!CreateDirectoryW(szUserProfilePath
, NULL
))
513 if (GetLastError() != ERROR_ALREADY_EXISTS
)
515 DPRINT1("Error: %lu\n", GetLastError());
519 for (i
= 0; i
< 1000; i
++)
521 swprintf(szUserProfileName
, L
"%s.%03u", lpUserName
, i
);
523 StringCbCopyW(szUserProfilePath
, sizeof(szUserProfilePath
), szProfilesPath
);
524 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), L
"\\");
525 StringCbCatW(szUserProfilePath
, sizeof(szUserProfilePath
), szUserProfileName
);
528 if (CreateDirectoryW(szUserProfilePath
, NULL
))
531 if (GetLastError() != ERROR_ALREADY_EXISTS
)
533 DPRINT1("Error: %lu\n", GetLastError());
539 /* Copy default user directory */
541 StringCbCopyW(szDefaultUserPath
, sizeof(szDefaultUserPath
), szProfilesPath
);
542 StringCbCatW(szDefaultUserPath
, sizeof(szDefaultUserPath
), L
"\\");
543 StringCbCatW(szDefaultUserPath
, sizeof(szDefaultUserPath
), szBuffer
);
546 if (!CopyDirectory(szUserProfilePath
, szDefaultUserPath
))
548 DPRINT1("Error: %lu\n", GetLastError());
552 /* Add profile to profile list */
553 if (!ConvertSidToStringSidW(pSid
,
556 DPRINT1("Error: %lu\n", GetLastError());
560 StringCbCopyW(szBuffer
, sizeof(szBuffer
),
561 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
562 StringCbCatW(szBuffer
, sizeof(szBuffer
), SidString
);
564 /* Create user profile key */
565 Error
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
569 REG_OPTION_NON_VOLATILE
,
574 if (Error
!= ERROR_SUCCESS
)
576 DPRINT1("Error: %lu\n", Error
);
581 /* Create non-expanded user profile path */
582 StringCbCopyW(szBuffer
, sizeof(szBuffer
), szRawProfilesPath
);
583 StringCbCatW(szBuffer
, sizeof(szBuffer
), L
"\\");
584 StringCbCatW(szBuffer
, sizeof(szBuffer
), szUserProfileName
);
586 /* Set 'ProfileImagePath' value (non-expanded) */
587 Error
= RegSetValueExW(hKey
,
592 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
593 if (Error
!= ERROR_SUCCESS
)
595 DPRINT1("Error: %lu\n", Error
);
601 /* Set 'Sid' value */
602 Error
= RegSetValueExW(hKey
,
608 if (Error
!= ERROR_SUCCESS
)
610 DPRINT1("Error: %lu\n", Error
);
618 /* Create user hive file */
620 /* Use the default hive file name */
621 StringCbCopyW(szBuffer
, sizeof(szBuffer
), szUserProfilePath
);
622 StringCbCatW(szBuffer
, sizeof(szBuffer
), L
"\\ntuser.dat");
624 /* Acquire restore privilege */
625 if (!AcquireRemoveRestorePrivilege(TRUE
))
627 Error
= GetLastError();
628 DPRINT1("Error: %lu\n", Error
);
633 /* Load the user hive */
634 Error
= RegLoadKeyW(HKEY_USERS
,
637 AcquireRemoveRestorePrivilege(FALSE
);
638 if (Error
!= ERROR_SUCCESS
)
640 DPRINT1("Error: %lu\n", Error
);
645 /* Initialize user hive */
646 if (!CreateUserHive(SidString
, szUserProfilePath
))
648 Error
= GetLastError();
649 DPRINT1("Error: %lu\n", Error
);
653 /* Unload the hive */
654 AcquireRemoveRestorePrivilege(TRUE
);
655 RegUnLoadKeyW(HKEY_USERS
, SidString
);
656 AcquireRemoveRestorePrivilege(FALSE
);
659 * If the caller wants to retrieve the user profile path,
660 * give it now. 'dwDirSize' is the number of characters.
662 if (lpProfileDir
&& dwDirSize
)
663 StringCchCopyW(lpProfileDir
, dwDirSize
, szUserProfilePath
);
666 LocalFree((HLOCAL
)SidString
);
667 SetLastError((DWORD
)Error
);
669 DPRINT("CreateUserProfileExW() done\n");
677 GetAllUsersProfileDirectoryA(
678 _Out_opt_ LPSTR lpProfileDir
,
679 _Inout_ LPDWORD lpcchSize
)
686 SetLastError(ERROR_INVALID_PARAMETER
);
690 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
691 *lpcchSize
* sizeof(WCHAR
));
692 if (lpBuffer
== NULL
)
695 bResult
= GetAllUsersProfileDirectoryW(lpBuffer
,
697 if (bResult
&& lpProfileDir
)
699 bResult
= WideCharToMultiByte(CP_ACP
,
709 GlobalFree(lpBuffer
);
717 GetAllUsersProfileDirectoryW(
718 _Out_opt_ LPWSTR lpProfileDir
,
719 _Inout_ LPDWORD lpcchSize
)
721 WCHAR szProfilePath
[MAX_PATH
];
722 WCHAR szBuffer
[MAX_PATH
];
723 DWORD dwType
, dwLength
;
729 SetLastError(ERROR_INVALID_PARAMETER
);
733 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
734 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
738 if (Error
!= ERROR_SUCCESS
)
740 DPRINT1("Error: %lu\n", Error
);
741 SetLastError((DWORD
)Error
);
745 /* Get profiles path */
746 dwLength
= sizeof(szBuffer
);
747 Error
= RegQueryValueExW(hKey
,
748 L
"ProfilesDirectory",
753 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
755 DPRINT1("Error: %lu\n", Error
);
757 SetLastError((DWORD
)Error
);
762 if (!ExpandEnvironmentStringsW(szBuffer
,
764 ARRAYSIZE(szProfilePath
)))
766 DPRINT1("Error: %lu\n", GetLastError());
771 /* Get 'AllUsersProfile' name */
772 dwLength
= sizeof(szBuffer
);
773 Error
= RegQueryValueExW(hKey
,
779 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
781 DPRINT1("Error: %lu\n", Error
);
783 SetLastError((DWORD
)Error
);
789 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), L
"\\");
790 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), szBuffer
);
792 dwLength
= wcslen(szProfilePath
) + 1;
793 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
795 StringCchCopyW(lpProfileDir
, *lpcchSize
, szProfilePath
);
796 *lpcchSize
= dwLength
;
799 else // if (!lpProfileDir || (*lpcchSize < dwLength))
801 *lpcchSize
= dwLength
;
802 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
810 GetDefaultUserProfileDirectoryA(
811 _Out_opt_ LPSTR lpProfileDir
,
812 _Inout_ LPDWORD lpcchSize
)
819 SetLastError(ERROR_INVALID_PARAMETER
);
823 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
824 *lpcchSize
* sizeof(WCHAR
));
825 if (lpBuffer
== NULL
)
828 bResult
= GetDefaultUserProfileDirectoryW(lpBuffer
,
830 if (bResult
&& lpProfileDir
)
832 bResult
= WideCharToMultiByte(CP_ACP
,
842 GlobalFree(lpBuffer
);
850 GetDefaultUserProfileDirectoryW(
851 _Out_opt_ LPWSTR lpProfileDir
,
852 _Inout_ LPDWORD lpcchSize
)
854 WCHAR szProfilePath
[MAX_PATH
];
855 WCHAR szBuffer
[MAX_PATH
];
856 DWORD dwType
, dwLength
;
862 SetLastError(ERROR_INVALID_PARAMETER
);
866 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
867 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
871 if (Error
!= ERROR_SUCCESS
)
873 DPRINT1("Error: %lu\n", Error
);
874 SetLastError((DWORD
)Error
);
878 /* Get profiles path */
879 dwLength
= sizeof(szBuffer
);
880 Error
= RegQueryValueExW(hKey
,
881 L
"ProfilesDirectory",
886 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
888 DPRINT1("Error: %lu\n", Error
);
890 SetLastError((DWORD
)Error
);
895 if (!ExpandEnvironmentStringsW(szBuffer
,
897 ARRAYSIZE(szProfilePath
)))
899 DPRINT1("Error: %lu\n", GetLastError());
904 /* Get 'DefaultUserProfile' name */
905 dwLength
= sizeof(szBuffer
);
906 Error
= RegQueryValueExW(hKey
,
907 L
"DefaultUserProfile",
912 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
914 DPRINT1("Error: %lu\n", Error
);
916 SetLastError((DWORD
)Error
);
922 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), L
"\\");
923 StringCbCatW(szProfilePath
, sizeof(szProfilePath
), szBuffer
);
925 dwLength
= wcslen(szProfilePath
) + 1;
926 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
928 StringCchCopyW(lpProfileDir
, *lpcchSize
, szProfilePath
);
929 *lpcchSize
= dwLength
;
932 else // if (!lpProfileDir || (*lpcchSize < dwLength))
934 *lpcchSize
= dwLength
;
935 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
943 GetProfilesDirectoryA(
944 _Out_ LPSTR lpProfileDir
, // _Out_opt_
945 _Inout_ LPDWORD lpcchSize
)
952 SetLastError(ERROR_INVALID_PARAMETER
);
956 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
957 *lpcchSize
* sizeof(WCHAR
));
958 if (lpBuffer
== NULL
)
961 bResult
= GetProfilesDirectoryW(lpBuffer
,
963 if (bResult
&& lpProfileDir
)
965 bResult
= WideCharToMultiByte(CP_ACP
,
975 GlobalFree(lpBuffer
);
983 GetProfilesDirectoryW(
984 _Out_ LPWSTR lpProfilesDir
, // _Out_opt_
985 _Inout_ LPDWORD lpcchSize
)
987 WCHAR szProfilesPath
[MAX_PATH
];
988 WCHAR szBuffer
[MAX_PATH
];
989 DWORD dwType
, dwLength
;
995 SetLastError(ERROR_INVALID_PARAMETER
);
999 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1000 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
1004 if (Error
!= ERROR_SUCCESS
)
1006 DPRINT1("Error: %lu\n", Error
);
1007 SetLastError((DWORD
)Error
);
1011 /* Get profiles path */
1012 dwLength
= sizeof(szBuffer
);
1013 Error
= RegQueryValueExW(hKey
,
1014 L
"ProfilesDirectory",
1019 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1021 DPRINT1("Error: %lu\n", Error
);
1023 SetLastError((DWORD
)Error
);
1030 if (!ExpandEnvironmentStringsW(szBuffer
,
1032 ARRAYSIZE(szProfilesPath
)))
1034 DPRINT1("Error: %lu\n", GetLastError());
1038 dwLength
= wcslen(szProfilesPath
) + 1;
1039 if (lpProfilesDir
&& (*lpcchSize
>= dwLength
))
1041 StringCchCopyW(lpProfilesDir
, *lpcchSize
, szProfilesPath
);
1042 *lpcchSize
= dwLength
;
1045 else // if (!lpProfilesDir || (*lpcchSize < dwLength))
1047 *lpcchSize
= dwLength
;
1048 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1056 GetUserProfileDirectoryA(
1058 _Out_opt_ LPSTR lpProfileDir
,
1059 _Inout_ LPDWORD lpcchSize
)
1066 SetLastError(ERROR_INVALID_PARAMETER
);
1070 lpBuffer
= GlobalAlloc(GMEM_FIXED
,
1071 *lpcchSize
* sizeof(WCHAR
));
1072 if (lpBuffer
== NULL
)
1075 bResult
= GetUserProfileDirectoryW(hToken
,
1078 if (bResult
&& lpProfileDir
)
1080 bResult
= WideCharToMultiByte(CP_ACP
,
1090 GlobalFree(lpBuffer
);
1098 GetUserProfileDirectoryW(
1100 _Out_opt_ LPWSTR lpProfileDir
,
1101 _Inout_ LPDWORD lpcchSize
)
1103 UNICODE_STRING SidString
;
1104 WCHAR szKeyName
[MAX_PATH
];
1105 WCHAR szRawImagePath
[MAX_PATH
];
1106 WCHAR szImagePath
[MAX_PATH
];
1107 DWORD dwType
, dwLength
;
1113 SetLastError(ERROR_INVALID_HANDLE
);
1119 SetLastError(ERROR_INVALID_PARAMETER
);
1123 /* Get the user SID string */
1124 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1126 DPRINT1("GetUserSidStringFromToken() failed\n");
1130 DPRINT("SidString: '%wZ'\n", &SidString
);
1132 StringCbCopyW(szKeyName
, sizeof(szKeyName
),
1133 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
1134 StringCbCatW(szKeyName
, sizeof(szKeyName
), SidString
.Buffer
);
1136 RtlFreeUnicodeString(&SidString
);
1138 DPRINT("KeyName: '%S'\n", szKeyName
);
1140 Error
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1145 if (Error
!= ERROR_SUCCESS
)
1147 DPRINT1("Error: %lu\n", Error
);
1148 SetLastError((DWORD
)Error
);
1152 dwLength
= sizeof(szRawImagePath
);
1153 Error
= RegQueryValueExW(hKey
,
1154 L
"ProfileImagePath",
1157 (LPBYTE
)szRawImagePath
,
1159 if ((Error
!= ERROR_SUCCESS
) || (dwType
!= REG_SZ
&& dwType
!= REG_EXPAND_SZ
))
1161 DPRINT1("Error: %lu\n", Error
);
1163 SetLastError((DWORD
)Error
);
1169 DPRINT("RawImagePath: '%S'\n", szRawImagePath
);
1172 if (!ExpandEnvironmentStringsW(szRawImagePath
,
1174 ARRAYSIZE(szImagePath
)))
1176 DPRINT1("Error: %lu\n", GetLastError());
1180 DPRINT("ImagePath: '%S'\n", szImagePath
);
1182 dwLength
= wcslen(szImagePath
) + 1;
1183 if (lpProfileDir
&& (*lpcchSize
>= dwLength
))
1185 StringCchCopyW(lpProfileDir
, *lpcchSize
, szImagePath
);
1186 *lpcchSize
= dwLength
;
1189 else // if (!lpProfileDir || (*lpcchSize < dwLength))
1191 *lpcchSize
= dwLength
;
1192 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1200 CheckForLoadedProfile(HANDLE hToken
)
1202 UNICODE_STRING SidString
;
1205 DPRINT("CheckForLoadedProfile() called\n");
1207 /* Get the user SID string */
1208 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1210 DPRINT1("GetUserSidStringFromToken() failed\n");
1214 if (RegOpenKeyExW(HKEY_USERS
,
1220 DPRINT("Profile not loaded\n");
1221 RtlFreeUnicodeString(&SidString
);
1227 RtlFreeUnicodeString(&SidString
);
1229 DPRINT("Profile already loaded\n");
1239 _Inout_ LPPROFILEINFOA lpProfileInfo
)
1241 BOOL bResult
= FALSE
;
1242 PROFILEINFOW ProfileInfoW
= {0};
1245 DPRINT("LoadUserProfileA() called\n");
1247 /* Check profile info */
1248 if (!lpProfileInfo
|| (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOA
)) ||
1249 (lpProfileInfo
->lpUserName
== NULL
) || (lpProfileInfo
->lpUserName
[0] == 0))
1251 SetLastError(ERROR_INVALID_PARAMETER
);
1255 /* Convert the structure to UNICODE... */
1256 ProfileInfoW
.dwSize
= sizeof(ProfileInfoW
);
1257 ProfileInfoW
.dwFlags
= lpProfileInfo
->dwFlags
;
1259 if (lpProfileInfo
->lpUserName
)
1261 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpUserName
, -1, NULL
, 0);
1262 ProfileInfoW
.lpUserName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1263 if (!ProfileInfoW
.lpUserName
)
1265 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1268 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpUserName
, -1, ProfileInfoW
.lpUserName
, len
);
1271 if (lpProfileInfo
->lpProfilePath
)
1273 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpProfilePath
, -1, NULL
, 0);
1274 ProfileInfoW
.lpProfilePath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1275 if (!ProfileInfoW
.lpProfilePath
)
1277 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1280 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpProfilePath
, -1, ProfileInfoW
.lpProfilePath
, len
);
1283 if (lpProfileInfo
->lpDefaultPath
)
1285 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpDefaultPath
, -1, NULL
, 0);
1286 ProfileInfoW
.lpDefaultPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1287 if (!ProfileInfoW
.lpDefaultPath
)
1289 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1292 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpDefaultPath
, -1, ProfileInfoW
.lpDefaultPath
, len
);
1295 if (lpProfileInfo
->lpServerName
)
1297 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpServerName
, -1, NULL
, 0);
1298 ProfileInfoW
.lpServerName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1299 if (!ProfileInfoW
.lpServerName
)
1301 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1304 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpServerName
, -1, ProfileInfoW
.lpServerName
, len
);
1307 if ((ProfileInfoW
.dwFlags
& PI_APPLYPOLICY
) != 0 && lpProfileInfo
->lpPolicyPath
)
1309 len
= MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpPolicyPath
, -1, NULL
, 0);
1310 ProfileInfoW
.lpPolicyPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1311 if (!ProfileInfoW
.lpPolicyPath
)
1313 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1316 MultiByteToWideChar(CP_ACP
, 0, lpProfileInfo
->lpPolicyPath
, -1, ProfileInfoW
.lpPolicyPath
, len
);
1319 /* ... and call the UNICODE function */
1320 bResult
= LoadUserProfileW(hToken
, &ProfileInfoW
);
1322 /* Save the returned value */
1323 lpProfileInfo
->hProfile
= ProfileInfoW
.hProfile
;
1326 /* Memory cleanup */
1327 if (ProfileInfoW
.lpUserName
)
1328 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpUserName
);
1330 if (ProfileInfoW
.lpProfilePath
)
1331 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpProfilePath
);
1333 if (ProfileInfoW
.lpDefaultPath
)
1334 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpDefaultPath
);
1336 if (ProfileInfoW
.lpServerName
)
1337 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpServerName
);
1339 if ((ProfileInfoW
.dwFlags
& PI_APPLYPOLICY
) != 0 && ProfileInfoW
.lpPolicyPath
)
1340 HeapFree(GetProcessHeap(), 0, ProfileInfoW
.lpPolicyPath
);
1350 _Inout_ LPPROFILEINFOW lpProfileInfo
)
1352 WCHAR szUserHivePath
[MAX_PATH
];
1353 PTOKEN_USER UserSid
= NULL
;
1354 UNICODE_STRING SidString
= { 0, 0, NULL
};
1357 DWORD dwLength
= sizeof(szUserHivePath
) / sizeof(szUserHivePath
[0]);
1359 DPRINT("LoadUserProfileW(%p %p)\n", hToken
, lpProfileInfo
);
1361 /* Check profile info */
1362 if (!lpProfileInfo
|| (lpProfileInfo
->dwSize
!= sizeof(PROFILEINFOW
)) ||
1363 (lpProfileInfo
->lpUserName
== NULL
) || (lpProfileInfo
->lpUserName
[0] == 0))
1365 SetLastError(ERROR_INVALID_PARAMETER
);
1369 DPRINT("UserName: %S\n", lpProfileInfo
->lpUserName
);
1371 /* Don't load a profile twice */
1372 if (CheckForLoadedProfile(hToken
))
1374 DPRINT ("Profile already loaded\n");
1375 lpProfileInfo
->hProfile
= NULL
;
1379 if (lpProfileInfo
->lpProfilePath
)
1381 /* Use the caller's specified roaming user profile path */
1382 StringCbCopyW(szUserHivePath
, sizeof(szUserHivePath
), lpProfileInfo
->lpProfilePath
);
1386 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
1387 if (!GetProfilesDirectoryW(szUserHivePath
, &dwLength
))
1389 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
1394 /* Create user hive name */
1395 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\");
1396 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), lpProfileInfo
->lpUserName
);
1397 StringCbCatW(szUserHivePath
, sizeof(szUserHivePath
), L
"\\ntuser.dat");
1398 DPRINT("szUserHivePath: %S\n", szUserHivePath
);
1400 /* Create user profile directory if needed */
1401 if (GetFileAttributesW(szUserHivePath
) == INVALID_FILE_ATTRIBUTES
)
1404 if (GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &dwLength
) ||
1405 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1407 DPRINT1 ("GetTokenInformation() failed\n");
1411 UserSid
= (PTOKEN_USER
)HeapAlloc(GetProcessHeap(), 0, dwLength
);
1414 DPRINT1("HeapAlloc() failed\n");
1415 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1419 if (!GetTokenInformation(hToken
, TokenUser
, UserSid
, dwLength
, &dwLength
))
1421 DPRINT1("GetTokenInformation() failed\n");
1425 /* Create profile */
1426 ret
= CreateUserProfileW(UserSid
->User
.Sid
, lpProfileInfo
->lpUserName
);
1429 DPRINT1("CreateUserProfileW() failed\n");
1434 /* Get the user SID string */
1435 ret
= GetUserSidStringFromToken(hToken
, &SidString
);
1438 DPRINT1("GetUserSidStringFromToken() failed\n");
1443 /* Acquire restore privilege */
1444 if (!AcquireRemoveRestorePrivilege(TRUE
))
1446 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1450 /* Load user registry hive */
1451 Error
= RegLoadKeyW(HKEY_USERS
,
1454 AcquireRemoveRestorePrivilege(FALSE
);
1456 /* HACK: Do not fail if the profile has already been loaded! */
1457 if (Error
== ERROR_SHARING_VIOLATION
)
1458 Error
= ERROR_SUCCESS
;
1460 if (Error
!= ERROR_SUCCESS
)
1462 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error
);
1463 SetLastError((DWORD
)Error
);
1467 /* Open future HKEY_CURRENT_USER */
1468 Error
= RegOpenKeyExW(HKEY_USERS
,
1472 (PHKEY
)&lpProfileInfo
->hProfile
);
1473 if (Error
!= ERROR_SUCCESS
)
1475 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error
);
1476 SetLastError((DWORD
)Error
);
1483 HeapFree(GetProcessHeap(), 0, UserSid
);
1484 RtlFreeUnicodeString(&SidString
);
1486 DPRINT("LoadUserProfileW() done\n");
1495 _In_ HANDLE hProfile
)
1497 UNICODE_STRING SidString
;
1500 DPRINT("UnloadUserProfile() called\n");
1502 if (hProfile
== NULL
)
1504 DPRINT1("Invalid profile handle\n");
1505 SetLastError(ERROR_INVALID_PARAMETER
);
1509 RegCloseKey(hProfile
);
1511 /* Get the user SID string */
1512 if (!GetUserSidStringFromToken(hToken
, &SidString
))
1514 DPRINT1("GetUserSidStringFromToken() failed\n");
1518 DPRINT("SidString: '%wZ'\n", &SidString
);
1520 /* Acquire restore privilege */
1521 if (!AcquireRemoveRestorePrivilege(TRUE
))
1523 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1524 RtlFreeUnicodeString(&SidString
);
1532 Error
= RegOpenKeyExW(HKEY_USERS
,
1537 if (Error
== ERROR_SUCCESS
)
1539 RegDeleteKeyW(hUserKey
,
1540 L
"Volatile Environment");
1542 RegCloseKey(hUserKey
);
1547 /* Unload the hive */
1548 Error
= RegUnLoadKeyW(HKEY_USERS
,
1551 /* Remove restore privilege */
1552 AcquireRemoveRestorePrivilege(FALSE
);
1554 if (Error
!= ERROR_SUCCESS
)
1556 DPRINT1("RegUnLoadKeyW() failed (Error %ld)\n", Error
);
1557 RtlFreeUnicodeString(&SidString
);
1558 SetLastError((DWORD
)Error
);
1562 RtlFreeUnicodeString(&SidString
);
1564 DPRINT("UnloadUserProfile() done\n");
1573 _In_ LPCWSTR lpSidString
,
1574 _In_opt_ LPCWSTR lpProfilePath
,
1575 _In_opt_ LPCWSTR lpComputerName
)
1577 DPRINT1("DeleteProfileW() not implemented!\n");
1585 _In_ LPCSTR lpSidString
,
1586 _In_opt_ LPCSTR lpProfilePath
,
1587 _In_opt_ LPCSTR lpComputerName
)
1590 UNICODE_STRING SidString
, ProfilePath
, ComputerName
;
1592 DPRINT("DeleteProfileA() called\n");
1594 /* Conversion to UNICODE */
1596 RtlCreateUnicodeStringFromAsciiz(&SidString
,
1597 (LPSTR
)lpSidString
);
1600 RtlCreateUnicodeStringFromAsciiz(&ProfilePath
,
1601 (LPSTR
)lpProfilePath
);
1604 RtlCreateUnicodeStringFromAsciiz(&ComputerName
,
1605 (LPSTR
)lpComputerName
);
1607 /* Call the UNICODE function */
1608 bResult
= DeleteProfileW(SidString
.Buffer
,
1610 ComputerName
.Buffer
);
1612 /* Memory cleanup */
1614 RtlFreeUnicodeString(&SidString
);
1617 RtlFreeUnicodeString(&ProfilePath
);
1620 RtlFreeUnicodeString(&ComputerName
);
1628 GetProfileType(_Out_ PDWORD pdwFlags
)
1630 DPRINT1("GetProfileType() not implemented!\n");