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