Improve LoadUserProfileW, by creating the profile if it doesn't exist

svn path=/trunk/; revision=28241
This commit is contained in:
Hervé Poussineau 2007-08-08 08:26:44 +00:00
parent 32789f3a9e
commit 6d37743cf2

View file

@ -63,7 +63,7 @@ AppendSystemPostfix (LPWSTR lpName,
lpszPtr++;
}
if (wcslen(lpName) + wcslen(lpszPostfix) >= dwMaxLength)
if (wcslen(lpName) + wcslen(lpszPostfix) + 1 >= dwMaxLength)
{
DPRINT1("Error: buffer overflow\n");
SetLastError(ERROR_BUFFER_OVERFLOW);
@ -825,91 +825,174 @@ LoadUserProfileA (HANDLE hToken,
BOOL WINAPI
LoadUserProfileW (HANDLE hToken,
LPPROFILEINFOW lpProfileInfo)
LoadUserProfileW(
IN HANDLE hToken,
IN OUT LPPROFILEINFOW lpProfileInfo)
{
WCHAR szUserHivePath[MAX_PATH];
UNICODE_STRING SidString;
LONG Error;
DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
WCHAR szUserHivePath[MAX_PATH];
LPWSTR UserName = NULL, Domain = NULL;
DWORD UserNameLength = 0, DomainLength = 0;
PTOKEN_USER UserSid = NULL;
SID_NAME_USE AccountType;
UNICODE_STRING SidString = { 0, };
LONG Error;
BOOL ret = FALSE;
DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
DPRINT ("LoadUserProfileW() called\n");
DPRINT("LoadUserProfileW() called\n");
/* Check profile info */
if (lpProfileInfo->dwSize != sizeof(PROFILEINFOW) ||
lpProfileInfo->lpUserName == NULL ||
lpProfileInfo->lpUserName[0] == 0)
/* Check profile info */
if (!lpProfileInfo
|| lpProfileInfo->dwSize != sizeof(PROFILEINFOW)
|| lpProfileInfo->lpUserName == NULL
|| lpProfileInfo->lpUserName[0] == 0)
{
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
SetLastError(ERROR_INVALID_PARAMETER);
return TRUE;
}
/* Don't load a profile twice */
if (CheckForLoadedProfile (hToken))
/* Don't load a profile twice */
if (CheckForLoadedProfile(hToken))
{
DPRINT ("Profile already loaded\n");
lpProfileInfo->hProfile = NULL;
return TRUE;
DPRINT ("Profile already loaded\n");
lpProfileInfo->hProfile = NULL;
return TRUE;
}
if (!GetProfilesDirectoryW (szUserHivePath,
&dwLength))
if (!GetProfilesDirectoryW(szUserHivePath, &dwLength))
{
DPRINT1("GetProfilesDirectoryW() failed\n", GetLastError());
return FALSE;
DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
return FALSE;
}
wcscat (szUserHivePath, L"\\");
wcscat (szUserHivePath, lpProfileInfo->lpUserName);
if (!AppendSystemPostfix (szUserHivePath, MAX_PATH))
wcscat(szUserHivePath, L"\\");
wcscat(szUserHivePath, lpProfileInfo->lpUserName);
dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
if (!AppendSystemPostfix(szUserHivePath, dwLength))
{
DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
return FALSE;
DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
return FALSE;
}
/* Create user hive name */
wcscat (szUserHivePath, L"\\ntuser.dat");
/* Create user hive name */
wcscat(szUserHivePath, L"\\ntuser.dat");
DPRINT("szUserHivePath: %S\n", szUserHivePath);
DPRINT ("szUserHivePath: %S\n", szUserHivePath);
if (!GetUserSidFromToken (hToken,
&SidString))
/* Create user profile directory if needed */
if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES)
{
DPRINT1 ("GetUserSidFromToken() failed\n");
return FALSE;
/* Get user sid */
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength)
|| GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
DPRINT1 ("GetTokenInformation() failed\n");
return FALSE;
}
UserSid = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, dwLength);
if (!UserSid)
{
DPRINT1 ("HeapAlloc() failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
if (!GetTokenInformation(hToken, TokenUser, UserSid, dwLength, &dwLength))
{
DPRINT1 ("GetTokenInformation() failed\n");
goto cleanup;
}
/* Get user name */
do
{
if (UserNameLength > 0)
{
HeapFree(GetProcessHeap(), 0, UserName);
UserName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, UserNameLength * sizeof(WCHAR));
if (!UserName)
{
DPRINT1("HeapAlloc() failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
}
if (DomainLength > 0)
{
HeapFree(GetProcessHeap(), 0, Domain);
Domain = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, DomainLength * sizeof(WCHAR));
if (!Domain)
{
DPRINT1("HeapAlloc() failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
}
ret = LookupAccountSidW(
NULL, UserSid->User.Sid,
UserName, &UserNameLength,
Domain, &DomainLength,
&AccountType);
} while (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
if (!ret)
{
DPRINT1("LookupAccountSidW() failed\n");
goto cleanup;
}
/* Create profile */
/* FIXME: ignore Domain? */
DPRINT("UserName %S, Domain %S\n", UserName, Domain);
ret = CreateUserProfileW(UserSid->User.Sid, UserName);
if (!ret)
{
DPRINT1("CreateUserProfileW() failed\n");
goto cleanup;
}
}
DPRINT ("SidString: '%wZ'\n", &SidString);
Error = RegLoadKeyW (HKEY_USERS,
SidString.Buffer,
szUserHivePath);
if (Error != ERROR_SUCCESS)
/* Get user SID string */
ret = GetUserSidFromToken(hToken, &SidString);
if (!ret)
{
DPRINT1 ("RegLoadKeyW() failed (Error %ld)\n", Error);
RtlFreeUnicodeString (&SidString);
SetLastError((DWORD)Error);
return FALSE;
DPRINT1("GetUserSidFromToken() failed\n");
goto cleanup;
}
ret = FALSE;
/* Load user registry hive */
Error = RegLoadKeyW(HKEY_USERS,
SidString.Buffer,
szUserHivePath);
if (Error != ERROR_SUCCESS)
{
DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error);
SetLastError((DWORD)Error);
goto cleanup;
}
Error = RegOpenKeyExW (HKEY_USERS,
SidString.Buffer,
0,
MAXIMUM_ALLOWED,
(PHKEY)&lpProfileInfo->hProfile);
if (Error != ERROR_SUCCESS)
/* Open future HKEY_CURRENT_USER */
Error = RegOpenKeyExW(HKEY_USERS,
SidString.Buffer,
0,
MAXIMUM_ALLOWED,
(PHKEY)&lpProfileInfo->hProfile);
if (Error != ERROR_SUCCESS)
{
DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", Error);
RtlFreeUnicodeString (&SidString);
SetLastError((DWORD)Error);
return FALSE;
DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
SetLastError((DWORD)Error);
goto cleanup;
}
RtlFreeUnicodeString (&SidString);
ret = TRUE;
DPRINT ("LoadUserProfileW() done\n");
cleanup:
HeapFree(GetProcessHeap(), 0, UserSid);
HeapFree(GetProcessHeap(), 0, UserName);
HeapFree(GetProcessHeap(), 0, Domain);
RtlFreeUnicodeString(&SidString);
return TRUE;
DPRINT("LoadUserProfileW() done\n");
return ret;
}