BOOL WINAPI GetUserProfileDirectoryW( HANDLE hToken, LPWSTR lpProfileDir, LPDWORD lpcchSize ) { static const WCHAR slashW[] = {'\\',0}; TOKEN_USER *t; WCHAR *userW = NULL, *dirW = NULL; DWORD len, dir_len, domain_len; SID_NAME_USE use; BOOL ret = FALSE; TRACE( "%p %p %p\n", hToken, lpProfileDir, lpcchSize ); if (!lpcchSize) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } len = 0; GetTokenInformation( hToken, TokenUser, NULL, 0, &len ); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; if (!(t = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE; if (!GetTokenInformation( hToken, TokenUser, t, len, &len )) goto done; len = domain_len = 0; LookupAccountSidW( NULL, t->User.Sid, NULL, &len, NULL, &domain_len, NULL ); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto done; if (!(userW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto done; if (!LookupAccountSidW( NULL, t->User.Sid, userW, &len, NULL, &domain_len, &use )) goto done; dir_len = 0; GetProfilesDirectoryW( NULL, &dir_len ); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto done; if (!(dirW = HeapAlloc( GetProcessHeap(), 0, (dir_len + 1) * sizeof(WCHAR) ))) goto done; if (!GetProfilesDirectoryW( dirW, &dir_len )) goto done; len += dir_len + 2; if (*lpcchSize < len) { SetLastError( ERROR_INSUFFICIENT_BUFFER ); *lpcchSize = len; goto done; } strcpyW( lpProfileDir, dirW ); strcatW( lpProfileDir, slashW ); strcatW( lpProfileDir, userW ); *lpcchSize = len; ret = TRUE; done: HeapFree( GetProcessHeap(), 0, t ); HeapFree( GetProcessHeap(), 0, userW ); HeapFree( GetProcessHeap(), 0, dirW ); return ret; }
BOOL WINAPI GetProfilesDirectoryA(LPSTR lpProfileDir, LPDWORD lpcchSize) { LPWSTR lpBuffer; BOOL bResult; lpBuffer = GlobalAlloc(GMEM_FIXED, *lpcchSize * sizeof(WCHAR)); if (lpBuffer == NULL) return FALSE; bResult = GetProfilesDirectoryW(lpBuffer, lpcchSize); if (bResult) { WideCharToMultiByte(CP_ACP, 0, lpBuffer, -1, lpProfileDir, *lpcchSize, NULL, NULL); } GlobalFree(lpBuffer); return bResult; }
BOOL WINAPI LoadUserProfileW(IN HANDLE hToken, IN OUT LPPROFILEINFOW lpProfileInfo) { 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, 0, NULL }; LONG Error; BOOL ret = FALSE; DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]); DPRINT("LoadUserProfileW() called\n"); /* Check profile info */ if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOW)) || (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* Don't load a profile twice */ if (CheckForLoadedProfile(hToken)) { DPRINT ("Profile already loaded\n"); lpProfileInfo->hProfile = NULL; return TRUE; } if (lpProfileInfo->lpProfilePath) { wcscpy(szUserHivePath, lpProfileInfo->lpProfilePath); } else { /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */ if (!GetProfilesDirectoryW(szUserHivePath, &dwLength)) { DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError()); return FALSE; } } /* Create user hive name */ wcscat(szUserHivePath, L"\\"); wcscat(szUserHivePath, lpProfileInfo->lpUserName); wcscat(szUserHivePath, L"\\ntuser.dat"); DPRINT("szUserHivePath: %S\n", szUserHivePath); /* Create user profile directory if needed */ if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES) { /* 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; } } /* Get user SID string */ ret = GetUserSidFromToken(hToken, &SidString); if (!ret) { DPRINT1("GetUserSidFromToken() failed\n"); goto cleanup; } ret = FALSE; /* Acquire restore privilege */ if (!AcquireRemoveRestorePrivilege(TRUE)) { DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError()); goto cleanup; } /* Load user registry hive */ Error = RegLoadKeyW(HKEY_USERS, SidString.Buffer, szUserHivePath); AcquireRemoveRestorePrivilege(FALSE); if (Error != ERROR_SUCCESS) { DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error); SetLastError((DWORD)Error); goto cleanup; } /* 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); SetLastError((DWORD)Error); goto cleanup; } ret = TRUE; cleanup: HeapFree(GetProcessHeap(), 0, UserSid); HeapFree(GetProcessHeap(), 0, UserName); HeapFree(GetProcessHeap(), 0, Domain); RtlFreeUnicodeString(&SidString); DPRINT("LoadUserProfileW() done\n"); return ret; }
BOOL DoLoginTasks( IN OUT PGINA_CONTEXT pgContext, IN PWSTR UserName, IN PWSTR Domain, IN PWSTR Password) { EndDialog(pgContext->hSasNotice, WLX_SAS_ACTION_NONE); pgContext->hSasNotice = 0; LPWSTR ProfilePath = NULL; LPWSTR lpEnvironment = NULL; TOKEN_STATISTICS Stats; PWLX_PROFILE_V2_0 pProfile = NULL; DWORD cbStats, cbSize; BOOL bResult; if (!LogonUserW(UserName, Domain, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &pgContext->UserToken)) { WARN("LogonUserW() failed\n"); goto cleanup; } /* Get profile path */ cbSize = 0; bResult = GetProfilesDirectoryW(NULL, &cbSize); if (!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { ProfilePath = HeapAlloc(GetProcessHeap(), 0, cbSize * sizeof(WCHAR)); if (!ProfilePath) { WARN("HeapAlloc() failed\n"); goto cleanup; } bResult = GetProfilesDirectoryW(ProfilePath, &cbSize); } if (!bResult) { WARN("GetUserProfileDirectoryW() failed\n"); goto cleanup; } /* Allocate memory for profile */ pProfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WLX_PROFILE_V2_0)); if (!pProfile) { WARN("HeapAlloc() failed\n"); goto cleanup; } pProfile->dwType = WLX_PROFILE_TYPE_V2_0; pProfile->pszProfile = ProfilePath; lpEnvironment = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 32 * sizeof(WCHAR)); if (!lpEnvironment) { WARN("HeapAlloc() failed\n"); goto cleanup; } wcscpy(lpEnvironment, L"LOGONSERVER=\\\\Test"); pProfile->pszEnvironment = lpEnvironment; if (!GetTokenInformation(pgContext->UserToken, TokenStatistics, (PVOID)&Stats, sizeof(TOKEN_STATISTICS), &cbStats)) { WARN("Couldn't get Authentication id from user token!\n"); goto cleanup; } *pgContext->pAuthenticationId = Stats.AuthenticationId; pgContext->pMprNotifyInfo->pszUserName = DuplicationString(UserName); pgContext->pMprNotifyInfo->pszDomain = DuplicationString(Domain); pgContext->pMprNotifyInfo->pszPassword = DuplicationString(Password); pgContext->pMprNotifyInfo->pszOldPassword = NULL; *pgContext->pdwOptions = 0; *pgContext->pProfile = pProfile; return TRUE; cleanup: if (pProfile) { HeapFree(GetProcessHeap(), 0, pProfile->pszEnvironment); } HeapFree(GetProcessHeap(), 0, pProfile); HeapFree(GetProcessHeap(), 0, ProfilePath); return FALSE; }