2020-09-30 17:12:29 +02:00

5852 lines
152 KiB
C

//*************************************************************
//
// Profile management routines
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1995
// All rights reserved
//
//*************************************************************
#include "uenv.h"
//
// Local function proto-types
//
BOOL CheckNetDefaultProfile (LPPROFILE lpProfile);
BOOL ParseProfilePath(LPPROFILE lpProfile, LPTSTR lpProfilePath);
BOOL RestoreUserProfile(LPPROFILE lpProfile);
BOOL TestIfUserProfileLoaded(HANDLE hUserToken, LPPROFILEINFO lpProfileInfo);
BOOL GetTempProfileDir(LPPROFILE lpProfile, LPTSTR lpProfileImage);
BOOL ComputeLocalProfileName (LPPROFILE lpProfile, LPTSTR lpUserName,
LPTSTR lpProfileImage, DWORD cchMaxProfileImage,
LPTSTR lpExpProfileImage, DWORD cchMaxExpProfileImage);
BOOL CreateLocalProfileKey (LPPROFILE lpProfile, PHKEY phKey, BOOL *bKeyExists);
BOOL GetLocalProfileImage(LPPROFILE lpProfile, BOOL *bNewUser);
BOOL IsCentralProfileReachable(LPPROFILE lpProfile, BOOL *bCreateCentralProfile,
BOOL *bMandatory);
BOOL UpdateToLatestProfile(LPPROFILE lpProfile, LPTSTR lpCentralProfile,
LPTSTR lpLocalProfile, LPTSTR lpSidString);
BOOL IssueDefaultProfile (LPPROFILE lpProfile, LPTSTR lpDefaultProfile,
LPTSTR lpLocalProfile, LPTSTR lpSidString,
BOOL bMandatory);
BOOL UpgradeCentralProfile (LPPROFILE lpProfile, LPTSTR lpOldProfile);
BOOL UpgradeProfile (LPPROFILE lpProfile);
BOOL IsUserAGuest(LPPROFILE lpProfile);
BOOL IsUserAnAdminMember(LPPROFILE lpProfile);
BOOL SaveProfileInfo (LPPROFILE lpProfile);
LPPROFILE LoadProfileInfo(HANDLE hToken);
BOOL CheckForSlowLink(LPPROFILE lpProfile, DWORD dwTime);
BOOL APIENTRY SlowLinkDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
DWORD GetUserPreferenceValue(HANDLE hToken);
BOOL APIENTRY ChooseProfileDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD);
//*************************************************************
//
// LoadUserProfile()
//
// Purpose: Loads the user's profile, if unable to load
// use the cached profile or issue the default profile.
//
// Parameters: hToken - User's token
// lpProfileInfo - Profile Information
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/6/95 ericflo Created
//
//*************************************************************
BOOL WINAPI LoadUserProfile (HANDLE hToken, LPPROFILEINFO lpProfileInfo)
{
LPPROFILE lpProfile;
BOOL bResult = FALSE;
HANDLE hEvent = NULL;
TCHAR szEventName[MAX_PATH];
DWORD dwResult;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
#if DBG
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("=========================================================")));
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Entering, hToken = <0x%x>, lpProfileInfo = 0x%x"),
hToken, lpProfileInfo));
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->dwFlags = <0x%x>"),
lpProfileInfo->dwFlags));
if (lpProfileInfo->lpUserName) {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpUserName = <%s>"),
lpProfileInfo->lpUserName));
} else {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL user name!")));
}
if (lpProfileInfo->lpProfilePath) {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpProfilePath = <%s>"),
lpProfileInfo->lpProfilePath));
} else {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL central profile path")));
}
if (lpProfileInfo->lpDefaultPath) {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpDefaultPath = <%s>"),
lpProfileInfo->lpDefaultPath));
} else {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL default profile path")));
}
if (lpProfileInfo->lpServerName) {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpServerName = <%s>"),
lpProfileInfo->lpServerName));
} else {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL server name")));
}
if (lpProfileInfo->dwFlags & PI_APPLYPOLICY) {
if (lpProfileInfo->lpPolicyPath) {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpPolicyPath = <%s>"),
lpProfileInfo->lpPolicyPath));
} else {
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL policy path, but PI_APPLYPOLICY is set.")));
}
}
#endif
//
// Check Parameters
//
if (lpProfileInfo->dwSize != sizeof(PROFILEINFO)) {
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: lpProfileInfo->dwSize != sizeof(PROFILEINFO)")));
SetLastError(ERROR_INVALID_PARAMETER);
goto Exit;
}
if (!lpProfileInfo->lpUserName || !(*lpProfileInfo->lpUserName)) {
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: received a NULL pointer for lpUserName.")));
SetLastError(ERROR_INVALID_PARAMETER);
goto Exit;
}
//
// Create an event to prevent multiple threads/process from trying to
// load the profile at the same time.
//
wsprintf (szEventName, TEXT("userenv: %s"), lpProfileInfo->lpUserName);
CharLower (szEventName);
InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
SetSecurityDescriptorDacl (
&sd,
TRUE, // Dacl present
NULL, // NULL Dacl
FALSE // Not defaulted
);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
sa.nLength = sizeof( sa );
hEvent = CreateEvent ( &sa, TRUE, TRUE, szEventName);
if (!hEvent) {
if ( GetLastError() == ERROR_INVALID_HANDLE )
{
hEvent = OpenEvent( EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, szEventName );
}
if ( !hEvent )
{
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to create event %s. Error = %d."),
szEventName, GetLastError()));
goto Exit;
}
}
if ((WaitForSingleObject (hEvent, INFINITE) == WAIT_FAILED)) {
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to wait on the event. Error = %d."),
GetLastError()));
goto Exit;
}
//
// This will clear the event so other threads/process will have to
// wait in the WaitForSingleObject call.
//
ResetEvent (hEvent);
//
// Check if the profile is loaded already.
//
if (TestIfUserProfileLoaded(hToken, lpProfileInfo)) {
bResult = TRUE;
goto Exit;
}
//
// Allocate an internal Profile structure to work with.
//
lpProfile = (LPPROFILE) LocalAlloc (LPTR, sizeof(PROFILE));
if (!lpProfile) {
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to allocate memory")));
goto Exit;
}
//
// Save the data passed in.
//
lpProfile->dwFlags = lpProfileInfo->dwFlags;
lpProfile->dwUserPreference = GetUserPreferenceValue(hToken);
lpProfile->hToken = hToken;
lstrcpy (lpProfile->szUserName, lpProfileInfo->lpUserName);
if (lpProfileInfo->lpDefaultPath) {
lstrcpy (lpProfile->szDefaultProfile, lpProfileInfo->lpDefaultPath);
}
if (lpProfileInfo->lpServerName) {
lstrcpy (lpProfile->szServerName, lpProfileInfo->lpServerName);
}
if (lpProfileInfo->dwFlags & PI_APPLYPOLICY) {
if (lpProfileInfo->lpPolicyPath) {
lstrcpy (lpProfile->szPolicyPath, lpProfileInfo->lpPolicyPath);
}
}
//
// If there is a central profile, check for 3.x or 4.0 format.
//
if (lpProfileInfo->lpProfilePath && (*lpProfileInfo->lpProfilePath)) {
//
// Call ParseProfilePath to work some magic on it
//
if (!ParseProfilePath(lpProfile, lpProfileInfo->lpProfilePath)) {
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ParseProfilePath returned FALSE")));
SetLastError(ERROR_INVALID_PARAMETER);
LocalFree (lpProfile);
goto Exit;
}
//
// The real central profile directory is...
//
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: ParseProfilePath returned a directory of <%s>"),
lpProfile->szCentralProfile));
}
//
// Load the user's profile
//
if (!RestoreUserProfile(lpProfile)) {
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: RestoreUserProfile returned FALSE")));
LocalFree (lpProfile);
goto Exit;
}
//
// Set the USERPROFILE environment variable into this process's
// environmnet. This allows ExpandEnvironmentStrings to be used
// in the userdiff processing.
//
SetEnvironmentVariable (TEXT("USERPROFILE"), lpProfile->szLocalProfile);
//
// Upgrade the profile if appropriate.
//
if (!UpgradeProfile(lpProfile)) {
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: UpgradeProfile returned FALSE")));
}
//
// Apply Policy
//
if (lpProfile->dwFlags & PI_APPLYPOLICY) {
if (!ApplyPolicy(lpProfile)) {
DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ApplyPolicy returned FALSE")));
}
}
//
// Save the outgoing parameters
//
lpProfileInfo->hProfile = (HANDLE) lpProfile->hKeyCurrentUser;
//
// Save the profile information in the registry.
//
SaveProfileInfo (lpProfile);
//
// Free the structure
//
LocalFree (lpProfile);
//
// Success!
//
bResult = TRUE;
Exit:
if (hEvent) {
//
// This will set the event so other threads/process can continue.
//
SetEvent (hEvent);
CloseHandle (hEvent);
}
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Leaving with a value of %d. hProfile = <0x%x>"),
bResult, lpProfileInfo->hProfile));
DebugMsg((DM_VERBOSE, TEXT("=========================================================")));
return bResult;
}
//*************************************************************
//
// CheckNetDefaultProfile()
//
// Purpose: Checks if a network profile exists and
// caches it locally if it is valid.
//
// Parameters: lpProfile - Profile information
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: This routine assumes we are working
// in the user's context.
//
// History: Date Author Comment
// 9/21/95 ericflo Created
//
//*************************************************************
BOOL CheckNetDefaultProfile (LPPROFILE lpProfile)
{
HANDLE hFile;
WIN32_FIND_DATA fd;
TCHAR szBuffer[MAX_PATH];
TCHAR szLocalDir[MAX_PATH];
LPTSTR lpEnd;
BOOL bRetVal = TRUE;
BOOL bProfileReady =FALSE;
BOOL bDeleteLocal = FALSE;
LPTSTR lpNetPath = lpProfile->szDefaultProfile;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Entering, lpNetPath = <%s>"),
lpNetPath));
//
// Expand the local profile directory
//
ExpandEnvironmentStrings(DEFAULT_NET_PROFILE, szLocalDir, MAX_PATH);
//
// See if network copy exists
//
hFile = FindFirstFile (lpNetPath, &fd);
if (hFile != INVALID_HANDLE_VALUE) {
//
// Close the find handle
//
FindClose (hFile);
//
// We found something. Is it a directory?
//
if ( !(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: FindFirstFile found a file.")));
goto CheckLocal;
}
//
// Is there a ntuser.* file in this directory?
//
lstrcpy (szBuffer, lpNetPath);
lpEnd = CheckSlash (szBuffer);
lstrcpy (lpEnd, c_szNTUserStar);
hFile = FindFirstFile (szBuffer, &fd);
if (hFile == INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: FindFirstFile found a directory, but no ntuser files.")));
goto CheckLocal;
}
FindClose (hFile);
//
// We found a valid network profile.
//
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Found a valid network profile.")));
if (CopyProfileDirectory (lpNetPath, szLocalDir,
CPD_IGNORECOPYERRORS |
CPD_COPYIFDIFFERENT |
CPD_SYNCHRONIZE )) {
bProfileReady = TRUE;
goto Exit;
}
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Failed to copy network profile to local cache.")));
} else {
//
// If the network default user profile does not
// exist, then we want to delete it off of local
// machines.
//
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
bDeleteLocal = TRUE;
}
}
CheckLocal:
//
// See if local network copy exists
//
hFile = FindFirstFile (szLocalDir, &fd);
if (hFile != INVALID_HANDLE_VALUE) {
//
// Close the find handle
//
FindClose (hFile);
//
// We found something. Is it a directory?
//
if ( !(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: FindFirstFile found a file.")));
bRetVal = FALSE;
goto Exit;
}
//
// If the network copy has been deleted, then delete this
// local copy also and just use the normal Default User profile.
//
if (bDeleteLocal) {
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Removing local copy of network default user profile.")));
Delnode (szLocalDir);
goto Exit;
}
//
// Is there a ntuser.* file in this directory?
//
lstrcpy (szBuffer, szLocalDir);
lpEnd = CheckSlash (szBuffer);
lstrcpy (lpEnd, c_szNTUserStar);
hFile = FindFirstFile (szBuffer, &fd);
if (hFile == INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: FindFirstFile found a directory, but no ntuser files.")));
bRetVal = FALSE;
goto Exit;
}
FindClose (hFile);
//
// We found a valid local profile.
//
bProfileReady = TRUE;
}
Exit:
//
// If we are leaving successfully, then
// save the local profile directory.
//
if (bRetVal && bProfileReady) {
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: setting default profile to <%s>"), szLocalDir));
lstrcpy (lpProfile->szDefaultProfile, szLocalDir);
} else {
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: setting default profile to NULL")));
*lpProfile->szDefaultProfile = TEXT('\0');
}
//
// Tag the internal flags so we don't do this again.
//
lpProfile->dwInternalFlags |= DEFAULT_NET_READY;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Leaving with a value of %d."), bRetVal));
return bRetVal;
}
//*************************************************************
//
// ParseProfilePath()
//
// Purpose: Parses the profile path to determine if
// it points at a directory or a filename.
// If the path points to a filename, a subdirectory
// of a similar name is created.
//
// Parameters: lpProfile - Profile Information
// lpProfilePath - Input path
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/6/95 ericflo Created
//
//*************************************************************
BOOL ParseProfilePath(LPPROFILE lpProfile, LPTSTR lpProfilePath)
{
WIN32_FIND_DATA fd;
HANDLE hResult;
DWORD dwError;
TCHAR szProfilePath[MAX_PATH];
TCHAR szExt[5];
LPTSTR lpEnd;
UINT uiExtCount;
BOOL bRetVal = FALSE;
BOOL bUpgradeCentral = FALSE;
BOOL bMandatory = FALSE;
DWORD dwStart, dwDelta;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Entering, lpProfilePath = <%s>"),
lpProfilePath));
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Failed to impersonate user")));
return FALSE;
}
//
// Start by calling FindFirstFile so we have file attributes
// to work with.
//
dwStart = GetTickCount();
hResult = FindFirstFile(lpProfilePath, &fd);
dwDelta = GetTickCount() - dwStart;
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Tick Count = %d"), dwDelta));
//
// It's magic time...
//
if (hResult != INVALID_HANDLE_VALUE) {
//
// FindFirst File found something.
// First close the handle, then look at
// the file attributes.
//
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: FindFirstFile found something with attributes <0x%x>"),
fd.dwFileAttributes));
FindClose(hResult);
//
// If we found a directory, copy the path to
// the result buffer and exit.
//
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Found a directory")));
CheckForSlowLink (lpProfile, dwDelta);
lstrcpy (lpProfile->szCentralProfile, lpProfilePath);
bRetVal = TRUE;
goto Exit;
}
//
// We found a file.
// Jump to the filename generation code.
//
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Found a file")));
//
// We set this flag now, but it is only used if a new
// central directory is created.
//
bUpgradeCentral = TRUE;
goto GenerateDirectoryName;
}
//
// FindFirstFile failed. Look at the error to determine why.
//
dwError = GetLastError();
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: FindFirstFile failed with error %d"),
dwError));
if ( (dwError == ERROR_FILE_NOT_FOUND) ||
(dwError == ERROR_PATH_NOT_FOUND) ) {
DWORD dwStrLen;
//
// Nothing found with this name. If the name
// does not end in .usr or .man, attempt to create
// the directory.
//
dwStrLen = lstrlen (lpProfilePath);
if (dwStrLen >= 4) {
lpEnd = lpProfilePath + dwStrLen - 4;
if ( (lstrcmpi(lpEnd, c_szUSR) != 0) &&
(lstrcmpi(lpEnd, c_szMAN) != 0) ) {
if (CreateSecureDirectory(lpProfile, lpProfilePath, NULL)) {
//
// Successfully created the directory.
//
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Succesfully created the sub-directory")));
CheckForSlowLink (lpProfile, dwDelta);
lstrcpy (lpProfile->szCentralProfile, lpProfilePath);
bRetVal = TRUE;
goto Exit;
} else {
//
// Failed to create the subdirectory
//
DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Failed to create user sub-directory. Error = %d"),
GetLastError()));
}
}
}
}
else if (dwError == ERROR_ACCESS_DENIED) {
DebugMsg((DM_WARNING, TEXT("ParseProfilePath: You don't have permission to your central profile server! Error = %d"),
dwError));
if ((lpProfile->dwUserPreference != USERINFO_LOCAL) &&
!(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) {
ReportError(lpProfile->dwFlags, IDS_ACCESSDENIED, lpProfilePath);
}
goto DisableAndExit;
}
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Did not create the sub-directory. Generating a new name.")));
GenerateDirectoryName:
//
// If we made it here, either:
//
// 1) a file exists with the same name
// 2) the directory couldn't be created
// 3) the profile path ends in .usr or .man
//
// Make a local copy of the path so we can munge it.
//
lstrcpy (szProfilePath, lpProfilePath);
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Entering name generating code working with a path of <%s>."),
szProfilePath));
//
// Does this path have a filename extension?
//
lpEnd = szProfilePath + lstrlen (szProfilePath) - 1;
while (*lpEnd && (lpEnd >= szProfilePath)) {
if (*lpEnd == TEXT('.'))
break;
if (*lpEnd == TEXT('\\'))
break;
lpEnd--;
}
if (*lpEnd != TEXT('.')) {
//
// The path does not have an extension. Append .pds
//
lpEnd = szProfilePath + lstrlen (szProfilePath);
lstrcpy (lpEnd, c_szPDS);
} else {
//
// The path has an extension. Append the new
// directory extension (.pds or .pdm).
//
if (lstrcmpi(lpEnd, c_szMAN) == 0) {
lstrcpy (lpEnd, c_szPDM);
bMandatory = TRUE;
} else {
lstrcpy (lpEnd, c_szPDS);
}
}
//
// Call FindFirstFile to see if this directory exists.
//
hResult = FindFirstFile(szProfilePath, &fd);
if (hResult != INVALID_HANDLE_VALUE) {
//
// FindFirst File found something.
// First close the handle, then look at
// the file attributes.
//
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: FindFirstFile(2) found something with attributes <0x%x>"),
fd.dwFileAttributes));
FindClose(hResult);
//
// If we found a directory, copy the path to
// the result buffer and exit.
//
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Found a directory")));
if (bMandatory) {
lstrcpy (lpProfile->szCentralProfile, szProfilePath);
lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
} else {
CheckForSlowLink (lpProfile, dwDelta);
lstrcpy (lpProfile->szCentralProfile, szProfilePath);
}
bRetVal = TRUE;
goto Exit;
}
//
// We found a file that matches the generated name.
//
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Found a file with the name we generated.")));
if (!bMandatory) {
CheckForSlowLink (lpProfile, dwDelta);
}
if (bMandatory || ((lpProfile->dwUserPreference != USERINFO_LOCAL) &&
!(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK))) {
ReportError(lpProfile->dwFlags, IDS_FAILEDDIRCREATE, szProfilePath);
}
goto DisableAndExit;
}
//
// FindFirstFile failed. Look at the error to determine why.
//
dwError = GetLastError();
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: FindFirstFile failed with error %d"),
dwError));
//
// If we are working with a mandatory profile,
// disable the central profile and try to log
// on with a cache.
//
if (bMandatory) {
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Central mandatory profile is unreachable to due error %d."), dwError));
if (IsUserAnAdminMember(lpProfile)) {
ReportError(lpProfile->dwFlags, IDS_MANDATORY_NOT_AVAILABLE, dwError);
lpProfile->szCentralProfile[0] = TEXT('\0');
lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
bRetVal = TRUE;
} else {
ReportError(lpProfile->dwFlags, IDS_MANDATORY_NOT_AVAILABLE2, dwError);
}
goto Exit;
}
//
// The user has a roaming profile, so it is ok to call
// CheckForSlowLink now.
//
CheckForSlowLink (lpProfile, dwDelta);
if ( (dwError == ERROR_FILE_NOT_FOUND) ||
(dwError == ERROR_PATH_NOT_FOUND) ) {
//
// Attempt to create the directory.
//
if (CreateSecureDirectory(lpProfile, szProfilePath, NULL)) {
//
// Successfully created the directory.
//
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Succesfully created the sub-directory")));
lstrcpy (lpProfile->szCentralProfile, szProfilePath);
if (bUpgradeCentral) {
bRetVal = UpgradeCentralProfile (lpProfile, lpProfilePath);
} else {
bRetVal = TRUE;
}
if (bRetVal) {
//
// Success
//
CheckForSlowLink (lpProfile, dwDelta);
goto Exit;
} else {
//
// Delete the directory we created above.
//
Delnode (lpProfile->szCentralProfile);
}
} else {
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Failed to create the sub-directory")));
if ((lpProfile->dwUserPreference != USERINFO_LOCAL) &&
!(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) {
ReportError(lpProfile->dwFlags, IDS_FAILEDDIRCREATE2, szProfilePath, GetLastError());
}
goto DisableAndExit;
}
}
//
// The central profile isn't reachable, or failed to upgrade.
// Disable the central profile and try to log
// on with a cache.
//
dwError = GetLastError();
DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Central profile is unreachable to due error %d, switching to local profile only."), dwError));
if ((lpProfile->dwUserPreference != USERINFO_LOCAL) &&
!(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) {
ReportError(lpProfile->dwFlags, IDS_CENTRAL_NOT_AVAILABLE2, dwError);
}
DisableAndExit:
lpProfile->szCentralProfile[0] = TEXT('\0');
bRetVal = TRUE;
Exit:
//
// Revert to being 'ourself'
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Failed to revert to self")));
}
return bRetVal;
}
//*************************************************************
//
// RestoreUserProfile()
//
// Purpose: Downloads the user's profile if possible,
// otherwise use either cached profile or
// default profile.
//
// Parameters: lpProfile - Profile information
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/19/95 ericflo Created
//
//*************************************************************
BOOL RestoreUserProfile(LPPROFILE lpProfile)
{
BOOL IsCentralReachable = FALSE;
BOOL IsLocalReachable = FALSE;
BOOL IsMandatory = FALSE;
BOOL IsProfilePathNULL = FALSE;
BOOL bCreateCentralProfile = FALSE;
BOOL bDefaultUsed = FALSE;
LPTSTR lpCentralProfile;
LPTSTR lpLocalProfile;
BOOL bProfileLoaded = FALSE;
BOOL bNewUser = TRUE;
LPTSTR SidString;
LONG error = ERROR_SUCCESS;
TCHAR szProfile[MAX_PATH];
LPTSTR lpEnd;
BOOL bRet;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Entering")));
//
// Get the Sid string for the current user
//
SidString = GetSidString(lpProfile->hToken);
if (!SidString) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to get sid string for user")));
return FALSE;
}
//
// Initialization
//
lpCentralProfile = lpProfile->szCentralProfile;
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Profile path = <%s>"), lpCentralProfile ? lpCentralProfile : TEXT("")));
if (!lpCentralProfile || !(*lpCentralProfile)) {
IsProfilePathNULL = TRUE;
}
//
// Test if this user is a guest.
//
if (IsUserAGuest(lpProfile)) {
lpProfile->dwInternalFlags |= PROFILE_GUEST_USER;
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: User is a Guest")));
}
//
// Test if this user is an admin.
//
if (IsUserAnAdminMember(lpProfile)) {
lpProfile->dwInternalFlags |= PROFILE_ADMIN_USER;
lpProfile->dwInternalFlags &= ~PROFILE_GUEST_USER;
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: User is a Admin")));
}
//
// Decide if the central profilemage is available.
//
IsCentralReachable = IsCentralProfileReachable(lpProfile,
&bCreateCentralProfile,
&IsMandatory);
if (IsCentralReachable) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Central Profile is reachable")));
if (IsMandatory) {
lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Central Profile is mandatory")));
} else {
lpProfile->dwInternalFlags |= PROFILE_UPDATE_CENTRAL;
lpProfile->dwInternalFlags |= bCreateCentralProfile ? PROFILE_NEW_CENTRAL : 0;
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Central Profile is floating")));
if ((lpProfile->dwUserPreference == USERINFO_LOCAL) ||
(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Ignoring central profile due to User Preference of Local only (or slow link).")));
IsProfilePathNULL = TRUE;
IsCentralReachable = FALSE;
}
}
} else {
if (!IsProfilePathNULL) {
error = GetLastError();
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: IsCentralProfileReachable returned FALSE. error = %d"),
error));
ReportError(lpProfile->dwFlags, IDS_CENTRAL_NOT_AVAILABLE, error);
}
}
//
// Determine if the local copy of the profilemage is available.
//
IsLocalReachable = GetLocalProfileImage(lpProfile, &bNewUser);
if (IsLocalReachable) {
lpProfile->dwInternalFlags |= PROFILE_USE_CACHE;
lpProfile->dwInternalFlags |= bNewUser ? PROFILE_NEW_LOCAL : 0;
} else {
if (!GetTempProfileDir(lpProfile, lpProfile->szLocalProfile)) {
error = GetLastError();
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: GetTempProfileDir failed with error %d. Unable to issue temporary profile!"), error));
ReportError(lpProfile->dwFlags, IDS_TEMP_DIR_FAILED, lpProfile->szLocalProfile, error);
goto Exit;
}
}
lpLocalProfile = lpProfile->szLocalProfile;
DebugMsg((DM_VERBOSE, TEXT("Local profile %s reachable"), IsLocalReachable ? TEXT("is") : TEXT("is not")));
DebugMsg((DM_VERBOSE, TEXT("Local profile name is <%s>"), lpLocalProfile));
//
// We can do a couple of quick checks here to filter out
// new users.
//
if (( (lpProfile->dwInternalFlags & PROFILE_NEW_CENTRAL) &&
(lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL) ) ||
(!IsCentralReachable &&
(lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL) )) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Working with a new user. Go straight to issuing a default profile.")));
goto IssueDefault;
}
//
// If both central and local profileimages exist, reconcile them
// and load.
//
if (IsCentralReachable && IsLocalReachable) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: About to call UpdateToLatestProfile")));
bRet = UpdateToLatestProfile(lpProfile, lpCentralProfile, lpLocalProfile, SidString);
if (!bRet) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: UpdatetoLatestProfile failed. Issuing default profile")));
lpProfile->dwInternalFlags &= ~PROFILE_UPDATE_CENTRAL;
lpProfile->dwInternalFlags |= PROFILE_DELETE_CACHE;
goto IssueDefault;
}
lstrcpy (szProfile, lpLocalProfile);
lpEnd = CheckSlash(szProfile);
if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
lstrcpy (lpEnd, c_szNTUserMan);
} else {
lstrcpy (lpEnd, c_szNTUserDat);
}
error = MyRegLoadKey(lpProfile, HKEY_USERS, SidString, szProfile);
bProfileLoaded = (error == ERROR_SUCCESS);
//
// If we failed to load the central profile for some
// reason, don't update it when we log off.
//
if (bProfileLoaded) {
goto Exit;
} else {
lpProfile->dwInternalFlags &= ~PROFILE_UPDATE_CENTRAL;
lpProfile->dwInternalFlags |= PROFILE_DELETE_CACHE;
ReportError(lpProfile->dwFlags, IDS_FAILED_LOAD_LOCAL, error);
goto IssueDefault;
}
}
//
// Only a local profile exists so use it.
//
if (!IsCentralReachable && IsLocalReachable) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: No central profile. Attempting to load local profile.")));
lstrcpy (szProfile, lpLocalProfile);
lpEnd = CheckSlash(szProfile);
if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
lstrcpy (lpEnd, c_szNTUserMan);
} else {
lstrcpy (lpEnd, c_szNTUserDat);
}
error = MyRegLoadKey(lpProfile, HKEY_USERS, SidString, szProfile);
bProfileLoaded = (error == ERROR_SUCCESS);
if (!bProfileLoaded) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: MyRegLoadKey returned FALSE.")));
ReportError(lpProfile->dwFlags, IDS_FAILED_LOAD_LOCAL, error);
}
if (!bProfileLoaded && IsProfilePathNULL) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Failed to load local profile and profile path is NULL, going to overwrite local profile")));
lpProfile->dwInternalFlags |= PROFILE_DELETE_CACHE;
goto IssueDefault;
}
goto Exit;
}
//
// Last combination. Unable to access a local profile cache,
// but a central profile exists. Use the temporary profile.
//
if (IsCentralReachable) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Using temporary cache with central profile")));
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to impersonate user")));
goto Exit;
}
bRet = CopyProfileDirectory (lpCentralProfile,
lpLocalProfile,
CPD_IGNORECOPYERRORS |
CPD_COPYIFDIFFERENT |
CPD_SYNCHRONIZE);
//
// Revert to being 'ourself'
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to revert to self")));
}
//
// Check return value
//
if (!bRet) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: CopyProfileDirectory returned FALSE. Error = %d"), GetLastError()));
goto Exit;
}
lstrcpy (szProfile, lpLocalProfile);
lpEnd = CheckSlash(szProfile);
if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
lstrcpy (lpEnd, c_szNTUserMan);
} else {
lstrcpy (lpEnd, c_szNTUserDat);
}
error = MyRegLoadKey(lpProfile,HKEY_USERS,
SidString,
szProfile);
bProfileLoaded = (error == ERROR_SUCCESS);
if (bProfileLoaded) {
goto Exit;
}
//
// If a temporary cache exists, delete it, since we will
// generate a new one below.
//
if (!(lpProfile->dwInternalFlags & PROFILE_USE_CACHE)) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Deleting temporary profile directory <%s>."), lpLocalProfile));
if (!DeleteProfile (NULL, lpLocalProfile, TRUE)) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: DeleteProfile returned false. Error = %d"), GetLastError()));
}
}
}
IssueDefault:
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Issuing default profile")));
//
// If a cache exists, delete it, since we will
// generate a new one below.
//
if (lpProfile->dwInternalFlags & PROFILE_DELETE_CACHE) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Deleting cached profile directory <%s>."), lpLocalProfile));
lpProfile->dwInternalFlags &= ~PROFILE_DELETE_CACHE;
if (!DeleteProfile (SidString, lpLocalProfile, TRUE)) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: DeleteProfileDirectory returned false. Error = %d"), GetLastError()));
}
}
//
// Create a local profile to work with
//
if (!(lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL)) {
if (lpProfile->dwInternalFlags & PROFILE_USE_CACHE) {
if (!GetLocalProfileImage(lpProfile, &bNewUser)) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: GetLocalProfileImage failed.")));
ReportError(lpProfile->dwFlags, IDS_TEMP_DIR_FAILED, GetLastError());
goto Exit;
}
} else {
lstrcpy (szProfile, CONFIG_FILE_PATH);
if (!ComputeLocalProfileName(lpProfile, lpProfile->szUserName,
szProfile, MAX_PATH,
lpLocalProfile, MAX_PATH)) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: ComputeLocalProfileName failed.")));
goto Exit;
}
}
}
//
// If a default profile location was specified, try
// that first.
//
if ( !(lpProfile->dwInternalFlags & DEFAULT_NET_READY) ) {
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to impersonate user")));
goto IssueLocalDefault;
}
CheckNetDefaultProfile (lpProfile);
//
// Go back to system security context
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to revert to self")));
}
}
if ( lpProfile->szDefaultProfile && *lpProfile->szDefaultProfile) {
if (IssueDefaultProfile (lpProfile, lpProfile->szDefaultProfile,
lpLocalProfile, SidString,
(lpProfile->dwInternalFlags & PROFILE_MANDATORY))) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Successfully setup the specified default.")));
bProfileLoaded = TRUE;
goto IssueDefaultExit;
}
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: IssueDefaultProfile failed with specified default.")));
}
IssueLocalDefault:
//
// Issue the local default profile.
//
if (IssueDefaultProfile (lpProfile, DEFAULT_PROFILE,
lpLocalProfile, SidString,
(lpProfile->dwInternalFlags & PROFILE_MANDATORY))) {
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Successfully setup the local default.")));
bProfileLoaded = TRUE;
goto IssueDefaultExit;
}
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: IssueDefaultProfile failed with local default.")));
IssueDefaultExit:
//
// If the default profile was successfully issued, then
// we need to set the security on the hive.
//
if (bProfileLoaded) {
if (!SetupNewHive(lpProfile, SidString, NULL)) {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: SetupNewHive failed")));
bProfileLoaded = FALSE;
}
}
Exit:
//
// If the profile was loaded, then save the profile type in the
// user's hive, and setup the "User Shell Folders" section for
// Explorer.
//
if (bProfileLoaded) {
//
// Open the Current User key. This will be closed in
// UnloadUserProfile.
//
error = RegOpenKeyEx(HKEY_USERS, SidString, 0, KEY_ALL_ACCESS,
&lpProfile->hKeyCurrentUser);
if (error != ERROR_SUCCESS) {
bProfileLoaded = FALSE;
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to open current user key. Error = %d"), error));
}
}
if (!bProfileLoaded) {
//
// If the user is an Admin, then let him/her log on with
// either the .default profile, or an empty profile.
//
if (lpProfile->dwInternalFlags & PROFILE_ADMIN_USER) {
ReportError(lpProfile->dwFlags, IDS_ADMIN_OVERRIDE, GetLastError());
bProfileLoaded = TRUE;
} else {
DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to save settings in user hive or failed to apply security. Error = %d"), GetLastError()));
ReportError(lpProfile->dwFlags, IDS_FAILED_LOAD_PROFILE, GetLastError());
if (lpProfile->hKeyCurrentUser) {
RegCloseKey (lpProfile->hKeyCurrentUser);
}
MyRegUnLoadKey(HKEY_USERS, SidString);
}
}
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: About to Leave. Final Information follows:")));
DebugMsg((DM_VERBOSE, TEXT("Profile was %s loaded."), bProfileLoaded ? TEXT("successfully") : TEXT("NOT successfully")));
DebugMsg((DM_VERBOSE, TEXT("lpProfile->szCentralProfile = <%s>"), lpProfile->szCentralProfile));
DebugMsg((DM_VERBOSE, TEXT("lpProfile->szLocalProfile = <%s>"), lpProfile->szLocalProfile));
DebugMsg((DM_VERBOSE, TEXT("lpProfile->dwInternalFlags = 0x%x"), lpProfile->dwInternalFlags));
//
// Free up the user's sid string
//
DeleteSidString(SidString);
DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Leaving.")));
return bProfileLoaded;
}
//*************************************************************
//
// TestIfUserProfileLoaded()
//
// Purpose: Test to see if this user's profile is loaded.
//
// Parameters: hToken - user's token
// lpProfileInfo - Profile information from app
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/19/95 ericflo Ported
//
//*************************************************************
BOOL TestIfUserProfileLoaded(HANDLE hToken, LPPROFILEINFO lpProfileInfo)
{
LPTSTR SidString;
DWORD error;
HKEY hSubKey;
//
// Get the Sid string for the user
//
SidString = GetSidString(hToken);
if (!SidString) {
DebugMsg((DM_WARNING, TEXT("TestIfUserProfileLoaded: Failed to get sid string for user")));
return FALSE;
}
error = RegOpenKeyEx(HKEY_USERS, SidString, 0, KEY_ALL_ACCESS, &hSubKey);
if (error == ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE, TEXT("TestIfUserProfileLoaded: Profile already loaded.")));
//
// This key will be closed in UnloadUserProfile
//
lpProfileInfo->hProfile = (HANDLE) hSubKey;
}
DeleteSidString(SidString);
return(error == ERROR_SUCCESS);
}
//*************************************************************
//
// SecureUserKey()
//
// Purpose: Sets security on a key in the user's hive
// so only admin's can change it.
//
// Parameters: lpProfile - Profile Information
// lpKey - Key to secure
// pSid - Sid (used by CreateNewUser)
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/20/95 ericflo Created
//
//*************************************************************
BOOL SecureUserKey(LPPROFILE lpProfile, LPTSTR lpKey, PSID pSid)
{
DWORD Error, IgnoreError;
HKEY RootKey;
SECURITY_DESCRIPTOR sd;
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
PACL pAcl = NULL;
PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL;
DWORD cbAcl, AceIndex, dwDisp;
ACE_HEADER * lpAceHeader;
BOOL bRetVal = FALSE;
BOOL bFreeSid = TRUE;
DWORD dwFlags = 0;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Entering")));
//
// Create the security descriptor
//
//
// Give the user access by their real sid so they still have access
// when they logoff and logon again
//
if (pSid) {
psidUser = pSid;
bFreeSid = FALSE;
dwFlags = PI_NOUI;
} else {
psidUser = GetUserSid(lpProfile->hToken);
dwFlags = lpProfile->dwFlags;
}
if (!psidUser) {
DebugMsg((DM_WARNING, TEXT("SecureUserKey: Failed to get user sid")));
return FALSE;
}
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize system sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Get the admin sid
//
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
0, 0, 0, 0, &psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize admin sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Allocate space for the ACL
//
cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
(2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
(6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
if (!pAcl) {
goto Exit;
}
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize acl. Error = %d"), GetLastError()));
goto Exit;
}
//
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
//
AceIndex = 0;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUser)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for user. Error = %d"), GetLastError()));
goto Exit;
}
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for system. Error = %d"), GetLastError()));
goto Exit;
}
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for admin. Error = %d"), GetLastError()));
goto Exit;
}
//
// Now the inheritable ACEs
//
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidUser)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for user. Error = %d"), GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for system. Error = %d"), GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for admin. Error = %d"), GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize security descriptor. Error = %d"), GetLastError()));
goto Exit;
}
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
goto Exit;
}
//
// Open the root of the user's profile
//
Error = RegCreateKeyEx(HKEY_USERS,
lpKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
NULL,
&RootKey,
&dwDisp);
if (Error != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("SecureUserKey: Failed to open root of user registry, error = %d"), Error));
} else {
//
// Set the security descriptor on the key
//
Error = ApplySecurityToRegistryTree(RootKey, &sd);
if (Error == ERROR_SUCCESS) {
bRetVal = TRUE;
} else {
DebugMsg((DM_WARNING, TEXT("SecureUserKey: Failed to apply security to registry key, error = %d"), Error));
}
RegCloseKey(RootKey);
}
Exit:
//
// Free the sids and acl
//
if (bFreeSid && psidUser) {
DeleteUserSid (psidUser);
}
if (psidSystem) {
FreeSid(psidSystem);
}
if (psidAdmin) {
FreeSid(psidAdmin);
}
if (pAcl) {
GlobalFree (pAcl);
}
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Leaving with a return value of %d"), bRetVal));
return(bRetVal);
}
//end
//*************************************************************
//
// ApplySecurityToRegistryTree()
//
// Purpose: Applies the passed security descriptor to the passed
// key and all its descendants. Only the parts of
// the descriptor inddicated in the security
// info value are actually applied to each registry key.
//
// Parameters: RootKey - Registry key
// pSD - Security Descriptor
//
// Return: ERROR_SUCCESS if successful
//
// Comments:
//
// History: Date Author Comment
// 7/19/95 ericflo Created
//
//*************************************************************
DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
{
DWORD Error, IgnoreError;
DWORD SubKeyIndex;
LPTSTR SubKeyName;
HKEY SubKey;
DWORD cchSubKeySize = MAX_PATH + 1;
//
// First apply security
//
Error = RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
if (Error != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("ApplySecurityToRegistryTree: Failed to set security on registry key, error = %d"), Error));
return Error;
}
//
// Open each sub-key and apply security to its sub-tree
//
SubKeyIndex = 0;
SubKeyName = GlobalAlloc (GPTR, cchSubKeySize * sizeof(TCHAR));
if (!SubKeyName) {
DebugMsg((DM_WARNING, TEXT("ApplySecurityToRegistryTree: Failed to allocate memory, error = %d"), GetLastError()));
return GetLastError();
}
while (TRUE) {
//
// Get the next sub-key name
//
Error = RegEnumKey(RootKey, SubKeyIndex, SubKeyName, cchSubKeySize);
if (Error != ERROR_SUCCESS) {
if (Error == ERROR_NO_MORE_ITEMS) {
//
// Successful end of enumeration
//
Error = ERROR_SUCCESS;
} else {
DebugMsg((DM_WARNING, TEXT("ApplySecurityToRegistryTree: Registry enumeration failed with error = %d"), Error));
}
break;
}
//
// Open the sub-key
//
Error = RegOpenKeyEx(RootKey,
SubKeyName,
0,
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
&SubKey);
if (Error != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("ApplySecurityToRegistryKey : Failed to open sub-key %s, error = %d"), SubKeyName, Error));
break;
}
//
// Apply security to the sub-tree
//
Error = ApplySecurityToRegistryTree(SubKey, pSD);
//
// We're finished with the sub-key
//
IgnoreError = RegCloseKey(SubKey);
if (IgnoreError != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("ApplySecurityToRegistryKey : Failed to close registry key, error = %d"), Error));
}
//
// See if we set the security on the sub-tree successfully.
//
if (Error != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("ApplySecurityToRegistryKey : Failed to apply security to sub-key %s, error = %d"), SubKeyName, Error));
break;
}
//
// Go enumerate the next sub-key
//
SubKeyIndex ++;
}
GlobalFree (SubKeyName);
return Error;
}
//*************************************************************
//
// SetupNewHive()
//
// Purpose: Initializes the new user hive created by copying
// the default hive.
//
// Parameters: lpProfile - Profile Information
// lpSidString - Sid string
// pSid - Sid (used by CreateNewUser)
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/18/95 ericflo Created
//
//*************************************************************
BOOL SetupNewHive(LPPROFILE lpProfile, LPTSTR lpSidString, PSID pSid)
{
DWORD Error, IgnoreError;
HKEY RootKey;
SECURITY_DESCRIPTOR sd;
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
PACL pAcl = NULL;
PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL;
DWORD cbAcl, AceIndex;
ACE_HEADER * lpAceHeader;
BOOL bRetVal = FALSE;
BOOL bFreeSid = TRUE;
DWORD dwFlags = 0;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Entering")));
//
// Create the security descriptor that will be applied to each key
//
//
// Give the user access by their real sid so they still have access
// when they logoff and logon again
//
if (pSid) {
psidUser = pSid;
bFreeSid = FALSE;
dwFlags = PI_NOUI;
} else {
psidUser = GetUserSid(lpProfile->hToken);
dwFlags = lpProfile->dwFlags;
}
if (!psidUser) {
DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to get user sid")));
return FALSE;
}
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to initialize system sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Get the admin sid
//
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
0, 0, 0, 0, &psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to initialize admin sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Allocate space for the ACL
//
cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
(2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
(6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
if (!pAcl) {
goto Exit;
}
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to initialize acl. Error = %d"), GetLastError()));
goto Exit;
}
//
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
//
AceIndex = 0;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidUser)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to add ace for user. Error = %d"), GetLastError()));
goto Exit;
}
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to add ace for system. Error = %d"), GetLastError()));
goto Exit;
}
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to add ace for admin. Error = %d"), GetLastError()));
goto Exit;
}
//
// Now the inheritable ACEs
//
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to add ace for user. Error = %d"), GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to add ace for system. Error = %d"), GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
AceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to add ace for admin. Error = %d"), GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to initialize security descriptor. Error = %d"), GetLastError()));
goto Exit;
}
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
goto Exit;
}
//
// Open the root of the user's profile
//
Error = RegOpenKeyEx(HKEY_USERS,
lpSidString,
0,
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
&RootKey);
if (Error != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to open root of user registry, error = %d"), Error));
} else {
//
// Set the security descriptor on the entire tree
//
Error = ApplySecurityToRegistryTree(RootKey, &sd);
if (Error == ERROR_SUCCESS) {
TCHAR szSubKey[MAX_PATH];
//
// Change the security on certain keys in the user's registry
// so that only Admin's and the OS have write access.
//
lstrcpy (szSubKey, lpSidString);
lstrcat (szSubKey, TEXT("\\"));
lstrcat (szSubKey, POLICIES_KEY);
if (!SecureUserKey(lpProfile, szSubKey, pSid)) {
DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to secure policies key")));
}
bRetVal = TRUE;
} else {
DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to apply security to user registry tree, error = %d"), Error));
ReportError(dwFlags, IDS_SECURITY_FAILED, Error);
}
RegFlushKey (RootKey);
IgnoreError = RegCloseKey(RootKey);
if (IgnoreError != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to close reg key, error = %d"), IgnoreError));
}
}
Exit:
//
// Free the sids and acl
//
if (bFreeSid && psidUser) {
DeleteUserSid (psidUser);
}
if (psidSystem) {
FreeSid(psidSystem);
}
if (psidAdmin) {
FreeSid(psidAdmin);
}
if (pAcl) {
GlobalFree (pAcl);
}
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Leaving with a return value of %d"), bRetVal));
return(bRetVal);
}
//*************************************************************
//
// IsCentralProfileReachable()
//
// Purpose: Checks to see if the user can access the
// central profile.
//
// Parameters: lpProfile - User's token
// bCreateCentralProfile - Should the central profile be created
// bMandatory - Is this a mandatory profile
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/20/95 ericflo Ported
//
//*************************************************************
BOOL IsCentralProfileReachable(LPPROFILE lpProfile, BOOL *bCreateCentralProfile,
BOOL *bMandatory)
{
WIN32_FIND_DATA fd;
HANDLE hFile;
TCHAR szProfile[MAX_PATH];
LPTSTR lpProfilePath, lpEnd;
BOOL bRetVal = FALSE;
DWORD dwError;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Entering")));
//
// Setup default values
//
*bMandatory = FALSE;
*bCreateCentralProfile = FALSE;
//
// Check parameters
//
if (lpProfile->szCentralProfile[0] == TEXT('\0')) {
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Null path. Leaving")));
return FALSE;
}
lpProfilePath = lpProfile->szCentralProfile;
//
// Make sure we don't overrun our temporary buffer
//
if ((lstrlen(lpProfilePath) + 1 + lstrlen(c_szNTUserMan + 1)) > MAX_PATH) {
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Failed because temporary buffer is too small.")));
return FALSE;
}
//
// Copy the profile path to a temporary buffer
// we can munge it.
//
lstrcpy (szProfile, lpProfilePath);
//
// Add the slash if appropriate and then tack on
// ntuser.man.
//
lpEnd = CheckSlash(szProfile);
lstrcpy(lpEnd, c_szNTUserMan);
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Failed to impersonate user")));
return FALSE;
}
//
// See if this file exists
//
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Testing <%s>"), szProfile));
hFile = CreateFile(szProfile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Found a mandatory profile.")));
CloseHandle(hFile);
*bMandatory = TRUE;
bRetVal = TRUE;
goto Exit;
}
dwError = GetLastError();
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Profile is not reachable, error = %d"),
dwError));
//
// If we received an error other than file not
// found, bail now because we won't be able to
// access this location.
//
if (dwError != ERROR_FILE_NOT_FOUND) {
DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Profile path <%s> is not reachable, error = %d"),
szProfile, dwError));
goto Exit;
}
//
// Now try ntuser.dat
//
lstrcpy(lpEnd, c_szNTUserDat);
//
// See if this file exists.
//
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Testing <%s>"), szProfile));
hFile = CreateFile(szProfile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Found a user profile.")));
CloseHandle(hFile);
bRetVal = TRUE;
goto Exit;
}
dwError = GetLastError();
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Profile is not reachable, error = %d"),
dwError));
if (dwError == ERROR_FILE_NOT_FOUND) {
DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Ok to create a user profile.")));
*bCreateCentralProfile = TRUE;
bRetVal = TRUE;
goto Exit;
}
DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Profile path <%s> is not reachable(2), error = %d"),
szProfile, dwError));
Exit:
//
// Go back to system security context
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Failed to revert to self")));
}
return bRetVal;
}
//*************************************************************
//
// MyRegLoadKey()
//
// Purpose: Loads a hive into the registry
//
// Parameters: lpProfile - Profile Info
// hKey - Key to load the hive into
// lpSubKey - Subkey name
// lpFile - hive filename
//
// Return: ERROR_SUCCESS if successful
// Error number if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/22/95 ericflo Created
//
//*************************************************************
LONG MyRegLoadKey(LPPROFILE lpProfile, HKEY hKey,
LPTSTR lpSubKey, LPTSTR lpFile)
{
NTSTATUS Status;
BOOLEAN WasEnabled;
int error;
//
// Enable the restore privilege
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
if (NT_SUCCESS(Status)) {
error = RegLoadKey(hKey, lpSubKey, lpFile);
//
// Restore the privilege to its previous state
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
if (!NT_SUCCESS(Status)) {
DebugMsg((DM_WARNING, TEXT("MyRegLoadKey: Failed to restore RESTORE privilege to previous enabled state")));
}
//
// Check if the hive was loaded
//
if (error != ERROR_SUCCESS) {
ReportError(PI_NOUI, IDS_REGLOADKEYFAILED, error, lpFile);
DebugMsg((DM_WARNING, TEXT("MyRegLoadKey: Failed to load subkey <%s>, error =%d"), lpSubKey, error));
}
} else {
error = GetLastError();
DebugMsg((DM_WARNING, TEXT("MyRegLoadKey: Failed to enable restore privilege to load registry key")));
}
return error;
}
//*************************************************************
//
// MyRegUnLoadKey()
//
// Purpose: Unloads a registry key
//
// Parameters: hKey - Registry handle
// lpSubKey - Subkey to be unloaded
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/19/95 ericflo Ported
//
//*************************************************************
BOOL MyRegUnLoadKey(HKEY hKey, LPTSTR lpSubKey)
{
BOOL bResult = TRUE;
LONG error;
NTSTATUS Status;
BOOLEAN WasEnabled;
//
// Enable the restore privilege
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
if (NT_SUCCESS(Status)) {
error = RegUnLoadKey(hKey, lpSubKey);
if ( error != ERROR_SUCCESS) {
bResult = FALSE;
}
//
// Restore the privilege to its previous state
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
if (!NT_SUCCESS(Status)) {
DebugMsg((DM_WARNING, TEXT("MyRegUnLoadKey: Failed to restore RESTORE privilege to previous enabled state")));
}
} else {
DebugMsg((DM_WARNING, TEXT("MyRegUnloadKey: Failed to enable restore privilege to unload registry key")));
bResult = FALSE;
}
return bResult;
}
//*************************************************************
//
// UpgradeLocalProfile()
//
// Purpose: Upgrades a local profile from a 3.x profile
// to a profile directory structure.
//
// Parameters: lpProfile - Profile Information
// lpOldProfile - Previous profile file
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/6/95 ericflo Created
//
//*************************************************************
BOOL UpgradeLocalProfile (LPPROFILE lpProfile, LPTSTR lpOldProfile)
{
TCHAR szSrc[MAX_PATH];
TCHAR szDest[MAX_PATH];
LPTSTR lpSrcEnd, lpDestEnd;
BOOL bRetVal = FALSE;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("UpgradeLocalProfile: Entering")));
//
// Setup the temporary buffers
//
lstrcpy (szSrc, lpOldProfile);
lstrcpy (szDest, lpProfile->szLocalProfile);
lpDestEnd = CheckSlash (szDest);
lstrcpy (lpDestEnd, c_szNTUserDat);
//
// Copy the hive
//
if (!CopyFile(szSrc, szDest, FALSE)) {
DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: CopyFile failed to copy hive with error = %d"),
GetLastError()));
return FALSE;
}
//
// Delete the old hive
//
DeleteFile (szSrc);
//
// Copy log file
//
lstrcat (szSrc, c_szLog);
lstrcat (szDest, c_szLog);
if (!CopyFile(szSrc, szDest, FALSE)) {
DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: CopyFile failed to copy hive log with error = %d"),
GetLastError()));
}
//
// Delete the old hive log
//
DeleteFile (szSrc);
//
// Copy in the new shell folders from the default
//
if ( !(lpProfile->dwInternalFlags & DEFAULT_NET_READY) ) {
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to impersonate user")));
goto IssueLocalDefault;
}
CheckNetDefaultProfile (lpProfile);
//
// Go back to system security context
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to revert to self")));
}
}
if (lpProfile->szDefaultProfile && *lpProfile->szDefaultProfile) {
ExpandEnvironmentStrings(lpProfile->szDefaultProfile, szSrc, MAX_PATH);
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to impersonate user")));
goto IssueLocalDefault;
}
if (CopyProfileDirectory (szSrc, lpProfile->szLocalProfile,
CPD_IGNOREHIVE | CPD_IGNORECOPYERRORS)) {
bRetVal = TRUE;
}
//
// Go back to system security context
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to revert to self")));
}
}
IssueLocalDefault:
if (!bRetVal) {
ExpandEnvironmentStrings(DEFAULT_PROFILE, szSrc, MAX_PATH);
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to impersonate user")));
goto Exit;
}
bRetVal = CopyProfileDirectory (szSrc, lpProfile->szLocalProfile,
CPD_IGNOREHIVE | CPD_IGNORECOPYERRORS);
//
// Go back to system security context
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to revert to self")));
}
}
Exit:
if (bRetVal) {
lpProfile->dwInternalFlags |= PROFILE_RUN_SYNCAPP;
}
return bRetVal;
}
//*************************************************************
//
// UpgradeCentralProfile()
//
// Purpose: Upgrades a central profile from a 3.x profile
// to a profile directory structure.
//
// Parameters: lpProfile - Profile Information
// lpOldProfile - Previous profile file
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/6/95 ericflo Created
//
//*************************************************************
BOOL UpgradeCentralProfile (LPPROFILE lpProfile, LPTSTR lpOldProfile)
{
TCHAR szSrc[MAX_PATH];
TCHAR szDest[MAX_PATH];
LPTSTR lpSrcEnd, lpDestEnd, lpDot;
BOOL bRetVal = FALSE;
BOOL bMandatory = FALSE;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("UpgradeCentralProfile: Entering")));
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Failed to impersonate user")));
return FALSE;
}
//
// Setup the source buffer
//
lstrcpy (szSrc, lpOldProfile);
//
// Determine the profile type
//
lpDot = szSrc + lstrlen(szSrc) - 4;
if (*lpDot == TEXT('.')) {
if (!lstrcmpi (lpDot, c_szMAN)) {
bMandatory = TRUE;
}
}
//
// Setup the destination buffer
//
lstrcpy (szDest, lpProfile->szCentralProfile);
lpDestEnd = CheckSlash (szDest);
if (bMandatory) {
lstrcpy (lpDestEnd, c_szNTUserMan);
} else {
lstrcpy (lpDestEnd, c_szNTUserDat);
}
//
// Copy the hive
//
if (!CopyFile(szSrc, szDest, FALSE)) {
DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: CopyFile failed to copy hive with error = %d"),
GetLastError()));
DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Source = <%s>"), szSrc));
DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Destination = <%s>"), szDest));
goto Exit;
}
//
// Copy log file
//
lstrcpy (lpDot, c_szLog);
lstrcat (szDest, c_szLog);
if (!CopyFile(szSrc, szDest, FALSE)) {
DebugMsg((DM_VERBOSE, TEXT("UpgradeCentralProfile: CopyFile failed to copy hive log with error = %d"),
GetLastError()));
DebugMsg((DM_VERBOSE, TEXT("UpgradeCentralProfile: Source = <%s>"), szSrc));
DebugMsg((DM_VERBOSE, TEXT("UpgradeCentralProfile: Destination = <%s>"), szDest));
}
//
// Copy in the new shell folders from the default
//
if ( !(lpProfile->dwInternalFlags & DEFAULT_NET_READY) ) {
CheckNetDefaultProfile (lpProfile);
}
if (lpProfile->szDefaultProfile && *lpProfile->szDefaultProfile) {
ExpandEnvironmentStrings(lpProfile->szDefaultProfile, szSrc, MAX_PATH);
if (CopyProfileDirectory (szSrc, lpProfile->szCentralProfile,
CPD_IGNOREHIVE | CPD_IGNORECOPYERRORS)) {
bRetVal = TRUE;
}
}
if (!bRetVal) {
ExpandEnvironmentStrings(DEFAULT_PROFILE, szSrc, MAX_PATH);
bRetVal = CopyProfileDirectory (szSrc, lpProfile->szCentralProfile,
CPD_IGNOREHIVE | CPD_IGNORECOPYERRORS);
}
if (bRetVal) {
lpProfile->dwInternalFlags |= PROFILE_RUN_SYNCAPP;
}
Exit:
//
// Go back to system security context
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Failed to revert to self")));
}
return bRetVal;
}
//*************************************************************
//
// GetTempProfileDir()
//
// Purpose: Generates a temporary profile directory
//
// Parameters: lpProfile - Profile Information
// lpProfileImage - Receives the generated directory
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/20/95 ericflo Created
//
//*************************************************************
BOOL GetTempProfileDir (LPPROFILE lpProfile, LPTSTR lpProfileImage)
{
TCHAR szProfileImage[MAX_PATH];
TCHAR szExpProfileImage[MAX_PATH];
//
// Initialize the profile image
//
lstrcpy (szProfileImage, CONFIG_FILE_PATH);
//
// Call the compute function to do the real work.
//
if (ComputeLocalProfileName (lpProfile, TEMP_PROFILE_NAME_BASE,
szProfileImage, MAX_PATH,
szExpProfileImage, MAX_PATH)) {
//
// Save the generated name.
//
lstrcpy (lpProfileImage, szExpProfileImage);
return TRUE;
}
return FALSE;
}
//*************************************************************
//
// CreateSecureDirectory()
//
// Purpose: Creates a secure directory that only the user,
// admin, and system have access to.
//
// Parameters: lpProfile - Profile Information
// lpDirectory - Directory Name
// pSid - Sid (used by CreateUserProfile)
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/20/95 ericflo Created
//
//*************************************************************
BOOL CreateSecureDirectory (LPPROFILE lpProfile, LPTSTR lpDirectory, PSID pSid)
{
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
PACL pAcl = NULL;
PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL;
DWORD cbAcl, aceIndex;
ACE_HEADER * lpAceHeader;
BOOL bRetVal = FALSE;
BOOL bFreeSid = TRUE;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Entering with <%s>"), lpDirectory));
//
// Get the SIDs we'll need for the DACL
//
if (pSid) {
psidUser = pSid;
bFreeSid = FALSE;
} else {
psidUser = GetUserSid(lpProfile->hToken);
}
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to initialize system sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Get the Admin sid
//
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
0, 0, 0, 0, &psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to initialize admin sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Allocate space for the ACL
//
cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
(2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
(6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
if (!pAcl) {
goto Exit;
}
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to initialize acl. Error = %d"), GetLastError()));
goto Exit;
}
//
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
//
aceIndex = 0;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidUser)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
//
// Now the inheritable ACEs
//
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to initialize security descriptor. Error = %d"), GetLastError()));
goto Exit;
}
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
goto Exit;
}
//
// Add the security descriptor to the sa structure
//
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
//
// Attempt to create the directory
//
if (CreateNestedDirectory(lpDirectory, &sa)) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Created the directory <%s>"), lpDirectory));
bRetVal = TRUE;
} else {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to created the directory <%s>"), lpDirectory));
}
Exit:
if (bFreeSid && psidUser) {
DeleteUserSid (psidUser);
}
if (psidSystem) {
FreeSid(psidSystem);
}
if (psidAdmin) {
FreeSid(psidAdmin);
}
if (pAcl) {
GlobalFree (pAcl);
}
return bRetVal;
}
//*************************************************************
//
// ComputeLocalProfileName()
//
// Purpose: Constructs the pathname of the local profile
// for this user. It will attempt to create
// a directory of the username, and then if
// unsccessful it will try the username.xxx
// where xxx is a three digit number
//
// Parameters: lpProfile - Profile Information
// lpUserName - UserName
// lpProfileImage - Profile directory (unexpanded)
// cchMaxProfileImage - lpProfileImage buffer size
// lpExpProfileImage - Expanded directory
// cchMaxExpProfileImage - lpExpProfileImage buffer size
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: lpProfileImage should be initialized with the
// root profile path and the trailing backslash.
//
// History: Date Author Comment
// 6/20/95 ericflo Created
//
//*************************************************************
BOOL ComputeLocalProfileName (LPPROFILE lpProfile, LPTSTR lpUserName,
LPTSTR lpProfileImage, DWORD cchMaxProfileImage,
LPTSTR lpExpProfileImage, DWORD cchMaxExpProfileImage)
{
int i = 0;
TCHAR szNumber[5];
LPTSTR lpEnd;
DWORD dwProfileLen;
BOOL bRetVal = FALSE;
HANDLE hFile;
WIN32_FIND_DATA fd;
//
// Check buffer size
//
dwProfileLen = lstrlen(lpProfileImage);
if ((dwProfileLen + lstrlen(lpUserName) + 4 + 1) > cchMaxProfileImage) {
DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: buffer too small")));
return FALSE;
}
//
// Place the username onto the end of the profile image
//
lpEnd = lpProfileImage + dwProfileLen;
lstrcpy (lpEnd, lpUserName);
//
// Expand the profile path
//
ExpandEnvironmentStrings(lpProfileImage, lpExpProfileImage, cchMaxExpProfileImage);
//
// Does this directory exist?
//
hFile = FindFirstFile (lpExpProfileImage, &fd);
if (hFile == INVALID_HANDLE_VALUE) {
//
// Attempt to create the directory
//
if (CreateSecureDirectory(lpProfile, lpExpProfileImage, NULL)) {
DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: generated the profile directory <%s>"), lpExpProfileImage));
bRetVal = TRUE;
goto Exit;
}
} else {
FindClose (hFile);
}
//
// Failed to create the directory for some reason.
// Now try username.000, username.001, etc
//
lpEnd = lpProfileImage + lstrlen(lpProfileImage);
for (i=0; i < 1000; i++) {
//
// Convert the number to a string and attach it.
//
wsprintf (szNumber, TEXT(".%.3d"), i);
lstrcpy (lpEnd, szNumber);
//
// Expand the profile path
//
ExpandEnvironmentStrings(lpProfileImage, lpExpProfileImage, cchMaxExpProfileImage);
//
// Does this directory exist?
//
hFile = FindFirstFile (lpExpProfileImage, &fd);
if (hFile == INVALID_HANDLE_VALUE) {
//
// Attempt to create the directory
//
if (CreateSecureDirectory(lpProfile, lpExpProfileImage, NULL)) {
DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: generated the profile directory <%s>"), lpExpProfileImage));
bRetVal = TRUE;
goto Exit;
}
} else {
FindClose (hFile);
}
}
DebugMsg((DM_WARNING, TEXT("ComputeLocalProfileName: Could not generate a profile directory. Error = %d"), GetLastError()));
Exit:
return bRetVal;
}
//*************************************************************
//
// CreateLocalProfileKey()
//
// Purpose: Creates a registry key pointing at the user profile
//
// Parameters: lpProfile - Profile information
// phKey - Handle to registry key if successful
// bKeyExists - TRUE if the registry key already existed
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/20/95 ericflo Ported
//
//*************************************************************
BOOL CreateLocalProfileKey (LPPROFILE lpProfile, PHKEY phKey, BOOL *bKeyExists)
{
TCHAR LocalProfileKey[MAX_PATH];
DWORD Disposition;
DWORD RegErr = ERROR_SUCCESS + 1;
BOOL Result;
LPTSTR SidString;
SidString = GetSidString(lpProfile->hToken);
if (SidString != NULL) {
//
// Call the RegCreateKey api in the user's context
//
lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
lstrcat(LocalProfileKey, TEXT("\\"));
lstrcat(LocalProfileKey, SidString);
RegErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
KEY_READ | KEY_WRITE, NULL, phKey, &Disposition);
if (RegErr == ERROR_SUCCESS) {
*bKeyExists = (BOOL)(Disposition & REG_OPENED_EXISTING_KEY);
} else {
DebugMsg((DM_WARNING, TEXT("CreateLocalProfileKey: Failed trying to create the local profile key <%s>, error = %d."), LocalProfileKey, RegErr));
}
DeleteSidString(SidString);
}
return(RegErr == ERROR_SUCCESS);
}
//*************************************************************
//
// GetLocalProfileImage()
//
// Purpose: Create/opens the profileimagepath
//
// Parameters: lpProfile - Profile information
// bNewUser - set to TRUE if the default profile was issued.
//
// Return: TRUE if the profile image is reachable
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/20/95 ericflo Ported
//
//*************************************************************
BOOL GetLocalProfileImage(LPPROFILE lpProfile, BOOL *bNewUser)
{
HKEY hKey;
BOOL bKeyExists;
TCHAR lpProfileImage[MAX_PATH];
TCHAR lpExpProfileImage[MAX_PATH];
TCHAR lpOldProfileImage[MAX_PATH];
LPTSTR lpExpandedPath, lpEnd;
DWORD cbExpProfileImage = sizeof(TCHAR)*MAX_PATH;
HANDLE hFile;
WIN32_FIND_DATA fd;
DWORD cb;
DWORD err;
DWORD dwType;
HANDLE fh;
PSID UserSid;
BOOL bRetVal = FALSE;
BOOL bUpgradeLocal = FALSE;
lpProfile->szLocalProfile[0] = TEXT('\0');
*bNewUser = TRUE;
if (!CreateLocalProfileKey(lpProfile, &hKey, &bKeyExists)) {
return FALSE; // not reachable and cannot keep a local copy
}
if (bKeyExists) {
//
// Check if the local profile image is valid.
//
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: Found entry in profile list for existing local profile")));
err = RegQueryValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, 0, &dwType,
(LPBYTE)lpExpProfileImage, &cbExpProfileImage);
if (err == ERROR_SUCCESS && cbExpProfileImage) {
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: Local profile image filename = <%s>"), lpExpProfileImage));
if (dwType == REG_EXPAND_SZ) {
//
// Expand the profile image filename
//
cb = sizeof(lpExpProfileImage);
lpExpandedPath = LocalAlloc(LPTR, cb);
if (lpExpandedPath) {
ExpandEnvironmentStrings(lpExpProfileImage, lpExpandedPath, cb);
lstrcpy(lpExpProfileImage, lpExpandedPath);
LocalFree(lpExpandedPath);
}
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: Expanded local profile image filename = <%s>"), lpExpProfileImage));
}
//
// Call FindFirst to see if we need to migrate this profile
//
hFile = FindFirstFile (lpExpProfileImage, &fd);
if (hFile == INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: Local profile image filename we got from our profile list doesn't exit. Error = %d"), GetLastError()));
goto CreateLocal;
}
FindClose(hFile);
//
// If this is a file, then we need to migrate it to
//
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
lstrcpy (lpOldProfileImage, lpExpProfileImage);
bUpgradeLocal = TRUE;
goto CreateLocal;
}
//
// Test if a mandatory profile exists
//
lpEnd = CheckSlash (lpExpProfileImage);
lstrcpy (lpEnd, c_szNTUserMan);
fh = CreateFile(lpExpProfileImage, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh != INVALID_HANDLE_VALUE) {
lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
CloseHandle(fh);
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: Found local mandatory profile image file ok <%s>"),
lpExpProfileImage));
*(lpEnd - 1) = TEXT('\0');
lstrcpy(lpProfile->szLocalProfile, lpExpProfileImage);
RegCloseKey(hKey);
*bNewUser = FALSE;
return TRUE; // local copy is valid and reachable
} else {
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: No local mandatory profile. Error = %d"), GetLastError()));
}
//
// Test if a normal profile exists
//
lstrcpy (lpEnd, c_szNTUserDat);
fh = CreateFile(lpExpProfileImage, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh != INVALID_HANDLE_VALUE) {
CloseHandle(fh);
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: Found local profile image file ok <%s>"),
lpExpProfileImage));
*(lpEnd - 1) = TEXT('\0');
lstrcpy(lpProfile->szLocalProfile, lpExpProfileImage);
RegCloseKey(hKey);
*bNewUser = FALSE;
return TRUE; // local copy is valid and reachable
} else {
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: Local profile image filename we got from our profile list doesn't exit. <%s> Error = %d"),
lpExpProfileImage, GetLastError()));
}
}
}
CreateLocal:
//
// No local copy found, try to create a new one.
//
DebugMsg((DM_VERBOSE, TEXT("GetLocalProfileImage: One way or another we haven't got an existing local profile, try and create one")));
lstrcpy(lpProfileImage, CONFIG_FILE_PATH);
if (ComputeLocalProfileName(lpProfile, lpProfile->szUserName,
lpProfileImage, MAX_PATH,
lpExpProfileImage, MAX_PATH)) {
//
// Add this image file to our profile list for this user
//
err = RegSetValueEx(hKey,
PROFILE_IMAGE_VALUE_NAME,
0,
REG_EXPAND_SZ,
(LPBYTE)lpProfileImage,
sizeof(TCHAR)*(lstrlen(lpProfileImage) + 1));
if (err == ERROR_SUCCESS) {
lstrcpy(lpProfile->szLocalProfile, lpExpProfileImage);
//
// Get the sid of the logged on user
//
UserSid = GetUserSid(lpProfile->hToken);
if (UserSid != NULL) {
//
// Store the user sid under the Sid key of the local profile
//
err = RegSetValueEx(hKey,
TEXT("Sid"),
0,
REG_BINARY,
UserSid,
RtlLengthSid(UserSid));
if (err != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("GetLocalProfileImage: Failed to set 'sid' value of user in profile list, error = %d"), err));
}
//
// We're finished with the user sid
//
DeleteUserSid(UserSid);
//
// If we are upgrading a profile from a 3.5 machine
// do that now.
//
if (bUpgradeLocal) {
if (UpgradeLocalProfile (lpProfile, lpOldProfileImage)) {
*bNewUser = FALSE;
}
}
bRetVal = TRUE;
} else {
DebugMsg((DM_WARNING, TEXT("GetLocalProfileImage: Failed to get sid of logged on user, so unable to update profile list")));
}
} else {
DebugMsg((DM_WARNING, TEXT("GetLocalProfileImage: Failed to update profile list for user with local profile image filename, error = %d"), err));
}
}
err = RegCloseKey(hKey);
if (err != STATUS_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("GetLocalProfileImage: Failed to close registry key, error = %d"), err));
}
return bRetVal;
}
//*************************************************************
//
// UpdateToLatestProfile()
//
// Purpose: Determines which profile is newer, and
// updates the local cache.
//
// Parameters: lpProfile - Profile info
// lpCentralProfile - Central profile
// lpLocalProfile - Local profile
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/21/95 ericflo Created
//
//*************************************************************
BOOL UpdateToLatestProfile(LPPROFILE lpProfile, LPTSTR lpCentralProfile,
LPTSTR lpLocalProfile, LPTSTR lpSidString)
{
HANDLE hLocal;
HANDLE hCentral;
FILETIME ftLocal;
FILETIME ftCentral;
BOOL FromCentralToLocal;
int DlgReturn;
LONG lTimeCompare;
TCHAR szProfile[MAX_PATH];
LPTSTR lpEnd;
BOOL bRetVal;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("UpdateToLatestProfile: Entering. Central = <%s> Local = <%s>"),
lpCentralProfile, lpLocalProfile));
//
// Setup a temporary buffer to work with
//
lstrcpy (szProfile, lpCentralProfile);
lpEnd = CheckSlash (szProfile);
if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
lstrcpy (lpEnd, c_szNTUserMan);
} else {
lstrcpy (lpEnd, c_szNTUserDat);
}
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to impersonate user")));
return FALSE;
}
//
// Attempt to open the central profile
//
hCentral = CreateFile(szProfile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hCentral == INVALID_HANDLE_VALUE) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: couldn't open central profile, error = %d"), GetLastError()));
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to revert to self")));
}
return TRUE;
} else {
if (!GetFileTime(hCentral, NULL, NULL, &ftCentral)) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to query central profile file time. Error = %d"),
GetLastError()));
ftCentral.dwLowDateTime = 0;
ftCentral.dwHighDateTime = 0;
}
CloseHandle(hCentral);
}
//
// Revert to being 'ourself'
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to revert to self")));
}
//
// Re-initialize the temporary buffer to look
// at the local profile.
//
lstrcpy (szProfile, lpLocalProfile);
lpEnd = CheckSlash (szProfile);
if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
lstrcpy (lpEnd, c_szNTUserMan);
} else {
lstrcpy (lpEnd, c_szNTUserDat);
}
//
// Attempt to open the local profile
//
hLocal = CreateFile(szProfile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hLocal == INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE, TEXT("UpdateToLatestProfile: couldn't open local profile, error = %d"), GetLastError()));
ftLocal.dwLowDateTime = 0;
ftLocal.dwHighDateTime = 0;
} else {
if (!GetFileTime(hLocal, NULL, NULL, &ftLocal)) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to query local profile file time. Error = %d"),
GetLastError()));
ftLocal.dwLowDateTime = 0;
ftLocal.dwHighDateTime = 0;
}
CloseHandle(hLocal);
}
if (lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL) {
DebugMsg((DM_VERBOSE, TEXT("UpdateToLatestProfile: New local cach has been created. Forcing copy from central.")));
FromCentralToLocal = TRUE;
} else {
//
// Decide which file is the most uptodate and use that as the source
// for the copy
//
lTimeCompare = CompareFileTime(&ftCentral, &ftLocal);
if (lTimeCompare == -1) {
FromCentralToLocal = FALSE;
DebugMsg((DM_VERBOSE, TEXT("UpdateToLatestProfile: Local profile time stamp is newer than central time stamp.")));
}
else if (lTimeCompare == 1) {
FromCentralToLocal = TRUE;
DebugMsg((DM_VERBOSE, TEXT("UpdateToLatestProfile: Central profile time stamp is newer than local time stamp.")));
}
else {
DebugMsg((DM_VERBOSE, TEXT("UpdateToLatestProfile: Central and local profile times match.")));
return TRUE;
}
}
//
// If we have a mandatory profile and the cache is newer
// than the central, force the central to be downloaded again.
// We only want to use the cache if the central is not available.
//
if ((lpProfile->dwInternalFlags & PROFILE_MANDATORY) && !FromCentralToLocal) {
FromCentralToLocal = TRUE;
}
if (!FromCentralToLocal && !(lpProfile->dwFlags & PI_NOUI)) {
HKEY hKey;
LONG lResult;
DWORD dwType, dwSize, dwDlgTimeOut;
//
// Ask the user if ok to overwrite the central profile with the
// the local profile.
//
// Get the dialog box timeout
//
dwDlgTimeOut = PROFILE_DLG_TIMEOUT;
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WINLOGON_KEY,
0,
KEY_READ,
&hKey);
if (lResult == ERROR_SUCCESS) {
dwSize = sizeof(DWORD);
RegQueryValueEx (hKey,
TEXT("ProfileDlgTimeOut"),
NULL,
&dwType,
(LPBYTE) &dwDlgTimeOut,
&dwSize);
RegCloseKey (hKey);
}
if (dwDlgTimeOut > 0) {
DlgReturn = DialogBoxParam (g_hDllInstance, MAKEINTRESOURCE(IDD_CHOOSE_PROFILE),
NULL, ChooseProfileDlgProc, dwDlgTimeOut);
if (DlgReturn == IDNO) {
//
// The user doesn't want to overwrite the central profile.
// The central profile becomes the active profile and overwrites
// the local copy.
//
FromCentralToLocal = TRUE;
}
}
}
//
// If FromCentralToLocal is false, we can exit now,
// since we are going to use the cache.
//
if (!FromCentralToLocal) {
return TRUE;
}
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to impersonate user")));
return FALSE;
}
if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
bRetVal = CopyProfileDirectory (lpCentralProfile, lpLocalProfile,
CPD_IGNORECOPYERRORS |
CPD_COPYIFDIFFERENT |
CPD_SYNCHRONIZE);
} else {
bRetVal = CopyProfileDirectory (lpCentralProfile, lpLocalProfile,
CPD_IGNORECOPYERRORS |
CPD_COPYIFDIFFERENT |
CPD_SYNCHRONIZE);
}
//
// Revert to being 'ourself'
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: Failed to revert to self")));
}
if (!bRetVal) {
DebugMsg((DM_WARNING, TEXT("UpdateToLatestProfile: CopyProfileDirectory returned FALSE. Error = %d"), GetLastError()));
return FALSE;
}
DebugMsg((DM_VERBOSE, TEXT("UpdateToLatestProfile: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// IssueDefaultProfile()
//
// Purpose: Issues the specified default profile to a user
//
// Parameters: lpProfile - Profile Information
// lpDefaultProfile - Default profile location
// lpLocalProfile - Local profile location
// lpSidString - User's sid
// bMandatory - Issue mandatory profile
//
// Return: TRUE if profile was successfully setup
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/22/95 ericflo Created
//
//*************************************************************
BOOL IssueDefaultProfile (LPPROFILE lpProfile, LPTSTR lpDefaultProfile,
LPTSTR lpLocalProfile, LPTSTR lpSidString,
BOOL bMandatory)
{
LPTSTR lpEnd, lpTemp;
TCHAR szProfile[MAX_PATH];
TCHAR szTempProfile[MAX_PATH];
BOOL bProfileLoaded = FALSE;
WIN32_FIND_DATA fd;
HANDLE hFile;
LONG error;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Entering. lpDefaultProfile = <%s> lpLocalProfile = <%s>"),
lpDefaultProfile, lpLocalProfile));
//
// First expand the default profile
//
ExpandEnvironmentStrings(lpDefaultProfile, szProfile, MAX_PATH);
//
// Does the default profile directory exist?
//
hFile = FindFirstFile (szProfile, &fd);
if (hFile == INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Default profile <%s> does not exist."), szProfile));
return FALSE;
}
FindClose(hFile);
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("IssueDefaultProfile: Failed to impersonate user")));
return FALSE;
}
//
// Copy profile to user profile
//
if (!CopyProfileDirectory (szProfile, lpLocalProfile, CPD_FORCECOPY)) {
DebugMsg((DM_WARNING, TEXT("IssueDefaultProfile: CopyProfileDirectory returned FALSE. Error = %d"), GetLastError()));
return FALSE;
}
//
// Rename the profile is a mandatory one was requested.
//
lstrcpy (szProfile, lpLocalProfile);
lpEnd = CheckSlash (szProfile);
if (bMandatory) {
DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Mandatory profile was requested.")));
lstrcpy (szTempProfile, szProfile);
lstrcpy (lpEnd, c_szNTUserMan);
hFile = FindFirstFile (szProfile, &fd);
if (hFile != INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Mandatory profile already exists.")));
FindClose(hFile);
} else {
DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Renaming ntuser.dat to ntuser.man")));
lpTemp = CheckSlash(szTempProfile);
lstrcpy (lpTemp, c_szNTUserDat);
if (!MoveFile(szTempProfile, szProfile)) {
DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: MoveFile returned false. Error = %d"), GetLastError()));
}
}
} else {
lstrcpy (lpEnd, c_szNTUserDat);
}
//
// Revert to being 'ourself'
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("IssueDefaultProfile: Failed to revert to self")));
}
//
// Try to load the new profile
//
error = MyRegLoadKey(lpProfile,HKEY_USERS,
lpSidString,
szProfile);
bProfileLoaded = (error == ERROR_SUCCESS);
if (!bProfileLoaded) {
DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: MyRegLoadKey failed with error %d"),
error));
return FALSE;
}
//
// Set the sync app flag
//
lpProfile->dwInternalFlags |= PROFILE_RUN_SYNCAPP;
DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Leaving successfully")));
return TRUE;
}
//*************************************************************
//
// DeleteProfile()
//
// Purpose: Deletes the specified profile from the
// registry and disk.
//
// Parameters: lpSidString - Registry subkey
// lpProfileDir - Profile directory
// bBackup - Backup profile before deleting
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/23/95 ericflo Created
//
//*************************************************************
BOOL DeleteProfile (LPTSTR lpSidString, LPTSTR lpLocalProfile, BOOL bBackup)
{
LONG lResult;
TCHAR szTemp[MAX_PATH];
//
// Cleanup the registry first.
//
if (lpSidString && *lpSidString) {
lstrcpy(szTemp, PROFILE_LIST_PATH);
lstrcat(szTemp, TEXT("\\"));
lstrcat(szTemp, lpSidString);
lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szTemp);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("DeleteProfile: Unable to delete registry entry. Error = %d"), lResult));
return FALSE;
}
}
if (bBackup) {
//
// Generate the backup name
//
lstrcpy (szTemp, lpLocalProfile);
lstrcat (szTemp, c_szBAK);
//
// First delete any previous backup
//
Delnode (szTemp);
//
// Attempt to rename the directory
//
if (!MoveFileEx(lpLocalProfile, szTemp, 0)) {
DebugMsg((DM_VERBOSE, TEXT("DeleteProfile: Failed to rename the directory. Error = %d"), GetLastError()));
return FALSE;
}
} else {
if (!Delnode (lpLocalProfile)) {
DebugMsg((DM_WARNING, TEXT("DeleteProfile: Delnode failed. Error = %d"), GetLastError()));
return FALSE;
}
}
return TRUE;
}
//*************************************************************
//
// UpgradeProfile()
//
// Purpose: Called after a profile is successfully loaded.
// Stamps build number into the profile, and if
// appropriate upgrades the per-user settings
// that NT setup wants done.
//
// Parameters: lpProfile - Profile Information
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/7/95 ericflo Created
//
//*************************************************************
BOOL UpgradeProfile (LPPROFILE lpProfile)
{
HKEY hKey;
DWORD dwDisp, dwType, dwSize, dwBuildNumber;
LONG lResult;
BOOL bUpgrade = FALSE;
BOOL bRunSyncApp = FALSE;
BOOL bDoUserdiff = TRUE;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("UpgradeProfile: Entering")));
//
// Query for the build number
//
lResult = RegCreateKeyEx (lpProfile->hKeyCurrentUser, WINLOGON_KEY,
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("UpgradeProfile: Failed to open winlogon key. Error = %d"), lResult));
return FALSE;
}
dwSize = sizeof(dwBuildNumber);
lResult = RegQueryValueEx (hKey, PROFILE_BUILD_NUMBER,
NULL, &dwType, (LPBYTE)&dwBuildNumber,
&dwSize);
if (lResult == ERROR_SUCCESS) {
//
// Found the build number. If they match,
// we don't want to process the userdiff hive
//
if (dwBuildNumber == g_dwBuildNumber) {
DebugMsg((DM_VERBOSE, TEXT("UpgradeProfile: Build numbers match")));
bDoUserdiff = FALSE;
}
} else {
dwBuildNumber = 0;
}
if (bDoUserdiff) {
//
// Set the build number
//
lResult = RegSetValueEx (hKey, PROFILE_BUILD_NUMBER, 0, REG_DWORD,
(LPBYTE) &g_dwBuildNumber, sizeof(g_dwBuildNumber));
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("UpgradeProfile: Failed to set build number. Error = %d"), lResult));
}
}
//
// Set syncapp flag
//
if (lpProfile->dwInternalFlags & PROFILE_RUN_SYNCAPP) {
bRunSyncApp = TRUE;
lResult = RegSetValueEx (hKey, SYNCAPP_REG_VALUE_NAME, 0, REG_DWORD,
(LPBYTE) &bRunSyncApp, sizeof(bRunSyncApp));
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("UpgradeProfile: Failed to set syncapp flag. Error = %d"), lResult));
}
DebugMsg((DM_VERBOSE, TEXT("UpgradeProfile: Set syncapp flag to %d"), bRunSyncApp));
}
//
// Close the registry key
//
RegCloseKey (hKey);
if (bDoUserdiff) {
//
// Apply changes to user's hive that NT setup needs.
//
if (!ProcessUserDiff(lpProfile, dwBuildNumber)) {
DebugMsg((DM_WARNING, TEXT("UpgradeProfile: ProcessUserDiff failed")));
}
}
DebugMsg((DM_VERBOSE, TEXT("UpgradeProfile: Leaving Successfully")));
return TRUE;
}
//*************************************************************
//
// IsUserAGuest()
//
// Purpose: Determines if the user is a member of the guest group.
//
// Parameters: lpProfile - Profile Information
//
// Return: TRUE if user is a guest
// FALSE if not
// Comments:
//
// History: Date Author Comment
// 7/25/95 ericflo Created
//
//*************************************************************
BOOL IsUserAGuest(LPPROFILE lpProfile)
{
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
NTSTATUS Status;
ULONG InfoLength;
PTOKEN_GROUPS TokenGroupList;
ULONG GroupIndex;
BOOL FoundGuests;
PSID GuestsDomainSid;
//
// Create Guests domain sid.
//
Status = RtlAllocateAndInitializeSid(
&authNT,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_GUESTS,
0, 0, 0, 0, 0, 0,
&GuestsDomainSid
);
//
// Test if user is in the Guests domain
//
//
// Get a list of groups in the token
//
Status = NtQueryInformationToken(
lpProfile->hToken, // Handle
TokenGroups, // TokenInformationClass
NULL, // TokenInformation
0, // TokenInformationLength
&InfoLength // ReturnLength
);
if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_TOO_SMALL)) {
DebugMsg((DM_WARNING, TEXT("IsUserAGuest: Failed to get group info for guests token, status = 0x%x"), Status));
RtlFreeSid(GuestsDomainSid);
return FALSE;
}
TokenGroupList = GlobalAlloc(GPTR, InfoLength);
if (TokenGroupList == NULL) {
DebugMsg((DM_WARNING, TEXT("IsUserAGuest: Unable to allocate memory for token groups")));
RtlFreeSid(GuestsDomainSid);
return FALSE;
}
Status = NtQueryInformationToken(
lpProfile->hToken, // Handle
TokenGroups, // TokenInformationClass
TokenGroupList, // TokenInformation
InfoLength, // TokenInformationLength
&InfoLength // ReturnLength
);
if (!NT_SUCCESS(Status)) {
DebugMsg((DM_WARNING, TEXT("IsUserAGuest: Failed to query groups for guests token, status = 0x%x"), Status));
GlobalFree(TokenGroupList);
RtlFreeSid(GuestsDomainSid);
return FALSE;
}
//
// Search group list for guests alias
//
FoundGuests = FALSE;
for (GroupIndex=0; GroupIndex < TokenGroupList->GroupCount; GroupIndex++ ) {
if (RtlEqualSid(TokenGroupList->Groups[GroupIndex].Sid, GuestsDomainSid)) {
FoundGuests = TRUE;
break;
}
}
//
// Tidy up
//
GlobalFree(TokenGroupList);
RtlFreeSid(GuestsDomainSid);
return(FoundGuests);
}
//*************************************************************
//
// IsUserAnAdminMember()
//
// Purpose: Determines if the user is a member of the administrators group.
//
// Parameters: lpProfile - Profile Information
//
// Return: TRUE if user is a admin
// FALSE if not
// Comments:
//
// History: Date Author Comment
// 7/25/95 ericflo Created
//
//*************************************************************
BOOL IsUserAnAdminMember(LPPROFILE lpProfile)
{
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
NTSTATUS Status;
ULONG InfoLength;
PTOKEN_GROUPS TokenGroupList;
ULONG GroupIndex;
BOOL FoundAdmins;
PSID AdminsDomainSid;
//
// Create Admins domain sid.
//
Status = RtlAllocateAndInitializeSid(
&authNT,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdminsDomainSid
);
//
// Test if user is in the Admins domain
//
//
// Get a list of groups in the token
//
Status = NtQueryInformationToken(
lpProfile->hToken, // Handle
TokenGroups, // TokenInformationClass
NULL, // TokenInformation
0, // TokenInformationLength
&InfoLength // ReturnLength
);
if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_TOO_SMALL)) {
DebugMsg((DM_WARNING, TEXT("IsUserAnAdminMember: Failed to get group info for Admins token, status = 0x%x"), Status));
RtlFreeSid(AdminsDomainSid);
return FALSE;
}
TokenGroupList = GlobalAlloc(GPTR, InfoLength);
if (TokenGroupList == NULL) {
DebugMsg((DM_WARNING, TEXT("IsUserAnAdminMember: Unable to allocate memory for token groups")));
RtlFreeSid(AdminsDomainSid);
return FALSE;
}
Status = NtQueryInformationToken(
lpProfile->hToken, // Handle
TokenGroups, // TokenInformationClass
TokenGroupList, // TokenInformation
InfoLength, // TokenInformationLength
&InfoLength // ReturnLength
);
if (!NT_SUCCESS(Status)) {
DebugMsg((DM_WARNING, TEXT("IsUserAnAdminMember: Failed to query groups for Admins token, status = 0x%x"), Status));
GlobalFree(TokenGroupList);
RtlFreeSid(AdminsDomainSid);
return FALSE;
}
//
// Search group list for Admins alias
//
FoundAdmins = FALSE;
for (GroupIndex=0; GroupIndex < TokenGroupList->GroupCount; GroupIndex++ ) {
if (RtlEqualSid(TokenGroupList->Groups[GroupIndex].Sid, AdminsDomainSid)) {
FoundAdmins = TRUE;
break;
}
}
//
// Tidy up
//
GlobalFree(TokenGroupList);
RtlFreeSid(AdminsDomainSid);
return(FoundAdmins);
}
//*************************************************************
//
// SetProfileTime()
//
// Purpose: Sets the timestamp on the remote profile and
// local profile to be the same regardless of the
// file system type being used.
//
// Parameters: lpProfile - Profile Information
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 9/25/95 ericflo Ported
//
//*************************************************************
BOOL SetProfileTime(LPPROFILE lpProfile)
{
HANDLE hFileCentral;
HANDLE hFileLocal;
FILETIME ft;
TCHAR szProfile[MAX_PATH];
LPTSTR lpEnd;
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to impersonate user")));
return FALSE;
}
//
// Create the central filename
//
lstrcpy (szProfile, lpProfile->szCentralProfile);
lpEnd = CheckSlash (szProfile);
if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
lstrcpy (lpEnd, c_szNTUserMan);
} else {
lstrcpy (lpEnd, c_szNTUserDat);
}
hFileCentral = CreateFile(szProfile,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFileCentral == INVALID_HANDLE_VALUE) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't open central profile <%s>, error = %d"),
szProfile, GetLastError()));
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to revert to self")));
}
return FALSE;
} else {
if (!GetFileTime(hFileCentral, NULL, NULL, &ft)) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't get time of central profile, error = %d"), GetLastError()));
}
}
//
// Revert to being 'ourself'
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to revert to self")));
}
//
// Create the local filename
//
lstrcpy (szProfile, lpProfile->szLocalProfile);
lpEnd = CheckSlash (szProfile);
if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
lstrcpy (lpEnd, c_szNTUserMan);
} else {
lstrcpy (lpEnd, c_szNTUserDat);
}
hFileLocal = CreateFile(szProfile,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFileLocal == INVALID_HANDLE_VALUE) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't open local profile <%s>, error = %d"),
szProfile, GetLastError()));
} else {
if (!SetFileTime(hFileLocal, NULL, NULL, &ft)) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't set time on local profile, error = %d"), GetLastError()));
}
if (!GetFileTime(hFileLocal, NULL, NULL, &ft)) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't get time on local profile, error = %d"), GetLastError()));
}
CloseHandle(hFileLocal);
}
//
// Reset time of central profile in case of discrepencies in
// times of different file systems.
//
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to impersonate user")));
return FALSE;
}
//
// Set the time on the central profile
//
if (hFileCentral != INVALID_HANDLE_VALUE) {
if (!SetFileTime(hFileCentral, NULL, NULL, &ft)) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't set time on local profile, error = %d"), GetLastError()));
}
CloseHandle(hFileCentral);
}
//
// Revert to being 'ourself'
//
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to revert to self")));
}
return TRUE;
}
//*************************************************************
//
// IsCacheDeleted()
//
// Purpose: Determines if the locally cached copy of the
// roaming profile should be deleted.
//
// Parameters: void
//
// Return: TRUE if local cache should be deleted
// FALSE if not
//
// Comments:
//
// History: Date Author Comment
// 6/28/96 ericflo Created
//
//*************************************************************
BOOL IsCacheDeleted (void)
{
BOOL bRetVal = FALSE;
DWORD dwSize, dwType;
HKEY hKey;
//
// Open the winlogon registry key
//
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
WINLOGON_KEY,
0,
KEY_READ,
&hKey) == ERROR_SUCCESS) {
//
// Check for the flag.
//
dwSize = sizeof(BOOL);
RegQueryValueEx (hKey,
DELETE_ROAMING_CACHE,
NULL,
&dwType,
(LPBYTE) &bRetVal,
&dwSize);
RegCloseKey (hKey);
}
return bRetVal;
}
//*************************************************************
//
// UnloadUserProfile()
//
// Purpose: Unloads the user's profile.
//
// Parameters: hToken - User's token
// hProfile - Profile handle created in LoadUserProfile
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/7/95 ericflo Created
//
//*************************************************************
BOOL WINAPI UnloadUserProfile (HANDLE hToken, HANDLE hProfile)
{
LPPROFILE lpProfile = NULL;
LPTSTR lpSidString = NULL;
LONG err, IgnoreError;
BOOL bRet, bRetVal = FALSE;
HANDLE hEvent = NULL;
TCHAR szEventName[MAX_PATH];
DWORD dwResult;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Entering, hProfile = <0x%x>"),
hProfile));
//
// Check Parameters
//
if (!hProfile) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: received a NULL hProfile.")));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// Load profile information
//
lpProfile = LoadProfileInfo(hToken);
if (!lpProfile) {
RegCloseKey((HKEY)hProfile);
goto Exit;
}
//
// Restore the hKeyCurrentUser parameter
//
lpProfile->hKeyCurrentUser = (HKEY) hProfile;
//
// Get the Sid string for the current user
//
lpSidString = GetSidString(lpProfile->hToken);
if (!lpSidString) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to get sid string for user")));
goto Exit;
}
//
// Create an event to prevent multiple threads/process from trying to
// unload the profile at the same time.
//
wsprintf (szEventName, TEXT("userenv: %s"), lpSidString);
CharLower (szEventName);
InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
SetSecurityDescriptorDacl (
&sd,
TRUE, // Dacl present
NULL, // NULL Dacl
FALSE // Not defaulted
);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
sa.nLength = sizeof( sa );
hEvent = CreateEvent ( &sa, TRUE, TRUE, szEventName);
if (!hEvent) {
if ( GetLastError() == ERROR_INVALID_HANDLE )
{
hEvent = OpenEvent( EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, szEventName );
}
if ( !hEvent )
{
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to create event %s. Error = %d."),
szEventName, GetLastError()));
goto Exit;
}
}
if ((WaitForSingleObject (hEvent, INFINITE) == WAIT_FAILED)) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to wait on the event. Error = %d."),
GetLastError()));
goto Exit;
}
//
// This will clear the event so other threads/process will have to
// wait in the WaitForSingleObject call.
//
ResetEvent (hEvent);
//
// Flush out the profile which will also sync the log.
//
err = RegFlushKey(lpProfile->hKeyCurrentUser);
if (err != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to flush the current user key, error = %d"), err));
}
//
// Close the current user key that was opened in LoadUserProfile.
//
err = RegCloseKey(lpProfile->hKeyCurrentUser);
if (err != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to close the current user key, error = %d"), err));
}
//
// If this is a mandatory or a guest profile, unload it now.
// Guest profiles are always deleted so one guest can't see
// the profile of a previous guest.
//
if ((lpProfile->dwInternalFlags & PROFILE_MANDATORY) ||
(lpProfile->dwInternalFlags & PROFILE_GUEST_USER)) {
err = MyRegUnLoadKey(HKEY_USERS, lpSidString);
if (!err) {
DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Didn't unload the user profile because of error = %d"), GetLastError()));
bRetVal = TRUE;
goto Exit;
} else {
DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Succesfully unloaded mandatory/guest profile")));
}
IgnoreError = RegFlushKey(HKEY_USERS);
if (IgnoreError != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to flush HKEY_USERS, error = %d"), IgnoreError));
}
if (IsCacheDeleted() || (lpProfile->dwInternalFlags & PROFILE_GUEST_USER)) {
//
// Delete the profile
//
if (!DeleteProfile (lpSidString, lpProfile->szLocalProfile, FALSE)) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: DeleteProfileDirectory returned false. Error = %d"), GetLastError()));
}
}
if (err) {
bRetVal = TRUE;
}
goto Exit;
}
//
// Unload the profile
//
err = MyRegUnLoadKey(HKEY_USERS, lpSidString);
if (!err) {
DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Didn't unload user profile <err = %d>"), GetLastError()));
bRetVal = TRUE;
goto Exit;
} else {
DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Succesfully unloaded profile")));
}
//
// Copy local profileimage to remote profilepath
//
if ( ((lpProfile->dwInternalFlags & PROFILE_UPDATE_CENTRAL) ||
(lpProfile->dwInternalFlags & PROFILE_NEW_CENTRAL)) ) {
if ((lpProfile->dwUserPreference != USERINFO_LOCAL) &&
!(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) {
DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Copying profile back to %s"),
lpProfile->szCentralProfile));
//
// Impersonate the user
//
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to impersonate user")));
goto Exit;
}
bRet = CopyProfileDirectory (lpProfile->szLocalProfile,
lpProfile->szCentralProfile,
CPD_IGNORECOPYERRORS |
CPD_COPYIFDIFFERENT |
CPD_SYNCHRONIZE);
if (!RevertToSelf()) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to revert to self")));
}
//
// Check return value
//
if (!bRet) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: CopyProfileDirectory returned FALSE. Error = %d"), GetLastError()));
ReportError(lpProfile->dwFlags, IDS_CENTRAL_UPDATE_FAILED, GetLastError());
goto Exit;
}
//
// The profile is copied, now we want to make sure the timestamp on
// both the remote profile and the local copy are the same, so we don't
// ask the user to update when it's not necessary.
//
SetProfileTime(lpProfile);
if (IsCacheDeleted()) {
if (!DeleteProfile (lpSidString, lpProfile->szLocalProfile, FALSE)) {
DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: DeleteProfileDirectory returned false (2). Error = %d"), GetLastError()));
}
}
}
}
//
// Success
//
bRetVal = TRUE;
Exit:
if (hEvent) {
//
// This will set the event so other threads/process can continue.
//
SetEvent (hEvent);
CloseHandle (hEvent);
}
if (lpSidString) {
DeleteSidString(lpSidString);
}
if (lpProfile) {
LocalFree (lpProfile);
}
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Leaving with a return value of %d"), bRetVal));
return bRetVal;
}
//*************************************************************
//
// SaveProfileInfo()
//
// Purpose: Saves key parts of the lpProfile structure
// in the registry for UnloadUserProfile to use.
//
// Parameters: lpProfile - Profile information
//
// Return: (BOOL) TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 12/4/95 ericflo Created
//
//*************************************************************
BOOL SaveProfileInfo(LPPROFILE lpProfile)
{
LPTSTR SidString, lpEnd;
TCHAR LocalProfileKey[MAX_PATH];
LONG lResult;
HKEY hKey;
DWORD dwType, dwSize, dwCount, dwDisp;
//
// Get the Sid string for the user
//
SidString = GetSidString(lpProfile->hToken);
if (!SidString) {
DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to get sid string for user")));
return FALSE;
}
//
// Open the profile mapping
//
lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
lpEnd = CheckSlash (LocalProfileKey);
lstrcpy(lpEnd, SidString);
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE, TEXT("SaveProfileInfo: Failed to open profile mapping key with error %d"), lResult));
return FALSE;
}
//
// Save the flags
//
lResult = RegSetValueEx (hKey,
PROFILE_FLAGS,
0,
REG_DWORD,
(LPBYTE) &lpProfile->dwFlags,
sizeof(DWORD));
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE, TEXT("SaveProfileInfo: Failed to save flags with error %d"), lResult));
}
//
// Save the internal flags
//
lResult = RegSetValueEx (hKey,
PROFILE_STATE,
0,
REG_DWORD,
(LPBYTE) &lpProfile->dwInternalFlags,
sizeof(DWORD));
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE, TEXT("SaveProfileInfo: Failed to save flags2 with error %d"), lResult));
}
//
// Save the central profile path
//
lResult = RegSetValueEx (hKey,
PROFILE_CENTRAL_PROFILE,
0,
REG_SZ,
(LPBYTE) &lpProfile->szCentralProfile,
(lstrlen(lpProfile->szCentralProfile) + 1) * sizeof(TCHAR));
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE, TEXT("SaveProfileInfo: Failed to save central profile with error %d"), lResult));
}
RegCloseKey (hKey);
DeleteSidString(SidString);
return(TRUE);
}
//*************************************************************
//
// LoadProfileInfo()
//
// Purpose: Loads key parts of the lpProfile structure
// in the registry for UnloadUserProfile to use.
//
// Parameters: hToken - User's token
//
// Return: pointer to lpProfile is successful
// NULL if not
//
// Comments: This function doesn't re-initialize all of the
// fields in the PROFILE structure.
//
// History: Date Author Comment
// 12/5/95 ericflo Created
//
//*************************************************************
LPPROFILE LoadProfileInfo(HANDLE hToken)
{
LPPROFILE lpProfile;
LPTSTR SidString, lpEnd;
TCHAR szBuffer[MAX_PATH];
LONG lResult;
HKEY hKey;
DWORD dwType, dwSize;
//
// Allocate an internal Profile structure to work with.
//
lpProfile = (LPPROFILE) LocalAlloc (LPTR, sizeof(PROFILE));
if (!lpProfile) {
DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to allocate memory")));
return NULL;
}
//
// Save the data passed in.
//
lpProfile->hToken = hToken;
//
// Get the Sid string for the user
//
SidString = GetSidString(hToken);
if (!SidString) {
DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to get sid string for user")));
LocalFree (lpProfile);
return NULL;
}
//
// Open the profile mapping
//
lstrcpy(szBuffer, PROFILE_LIST_PATH);
lpEnd = CheckSlash (szBuffer);
lstrcpy(lpEnd, SidString);
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0,
KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to open profile mapping key with error %d"), lResult));
LocalFree (lpProfile);
return NULL;
}
//
// Query for the flags
//
dwSize = sizeof(DWORD);
lResult = RegQueryValueEx (hKey,
PROFILE_FLAGS,
NULL,
&dwType,
(LPBYTE) &lpProfile->dwFlags,
&dwSize);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query flags with error %d"), lResult));
LocalFree (lpProfile);
return NULL;
}
//
// Query for the internal flags
//
dwSize = sizeof(DWORD);
lResult = RegQueryValueEx (hKey,
PROFILE_STATE,
NULL,
&dwType,
(LPBYTE) &lpProfile->dwInternalFlags,
&dwSize);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query internal flags with error %d"), lResult));
LocalFree (lpProfile);
return NULL;
}
//
// Query for the user preference value
//
lpProfile->dwUserPreference = USERINFO_UNDEFINED;
dwSize = sizeof(DWORD);
RegQueryValueEx (hKey,
USER_PREFERENCE,
NULL,
&dwType,
(LPBYTE) &lpProfile->dwUserPreference,
&dwSize);
//
// Query for the central profile path
//
dwSize = MAX_PATH * 2;
lResult = RegQueryValueEx (hKey,
PROFILE_CENTRAL_PROFILE,
NULL,
&dwType,
(LPBYTE) &lpProfile->szCentralProfile,
&dwSize);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query central profile with error %d"), lResult));
LocalFree (lpProfile);
return NULL;
}
//
// Query for the local profile path. The local profile path
// needs to be expanded so read it into the temporary buffer.
//
dwSize = MAX_PATH * 2;
lResult = RegQueryValueEx (hKey,
PROFILE_IMAGE_VALUE_NAME,
NULL,
&dwType,
(LPBYTE) szBuffer,
&dwSize);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query local profile with error %d"), lResult));
LocalFree (lpProfile);
return NULL;
}
//
// Expand the local profile
//
ExpandEnvironmentStrings(szBuffer, lpProfile->szLocalProfile, MAX_PATH);
RegCloseKey (hKey);
DeleteSidString(SidString);
return(lpProfile);
}
//*************************************************************
//
// CheckForSlowLink()
//
// Purpose: Checks if the network connection is slow.
//
// Parameters: lpProfile - Profile Information
// dwTime - Time delta
//
// Return: TRUE if profile should be downloaded
// FALSE if not (use local)
//
// Comments:
//
// History: Date Author Comment
// 2/21/96 ericflo Created
//
//*************************************************************
BOOL CheckForSlowLink(LPPROFILE lpProfile, DWORD dwTime)
{
DWORD dwSlowTimeOut, dwSlowDlgTimeOut, dwSlowLinkDetectEnabled;
DWORD dwType, dwSize;
BOOL bRetVal;
HKEY hKey;
LONG lResult;
//
// If the user doesn't want pop-up's, then they always
// get their profile downloaded.
//
if (lpProfile->dwFlags & PI_NOUI) {
return TRUE;
}
//
// If the User Preferences states to always use the local
// profile then we can exit now with true. The profile
// won't actually be downloaded. In RestoreUserProfile,
// this will be filtered out, and only the local will be used.
//
if (lpProfile->dwUserPreference == USERINFO_LOCAL) {
return TRUE;
}
//
// Get the slow link detection flag, slow link timeout,
// and dialog box timeout values.
//
dwSlowTimeOut = SLOW_LINK_TIMEOUT;
dwSlowDlgTimeOut = PROFILE_DLG_TIMEOUT;
dwSlowLinkDetectEnabled = 1;
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WINLOGON_KEY,
0,
KEY_READ,
&hKey);
if (lResult == ERROR_SUCCESS) {
dwSize = sizeof(DWORD);
RegQueryValueEx (hKey,
TEXT("SlowLinkDetectEnabled"),
NULL,
&dwType,
(LPBYTE) &dwSlowLinkDetectEnabled,
&dwSize);
dwSize = sizeof(DWORD);
RegQueryValueEx (hKey,
TEXT("SlowLinkTimeOut"),
NULL,
&dwType,
(LPBYTE) &dwSlowTimeOut,
&dwSize);
dwSize = sizeof(DWORD);
RegQueryValueEx (hKey,
TEXT("ProfileDlgTimeOut"),
NULL,
&dwType,
(LPBYTE) &dwSlowDlgTimeOut,
&dwSize);
RegCloseKey (hKey);
}
//
// If slow link detection is disabled, then always download
// the profile.
//
if (!dwSlowLinkDetectEnabled) {
return TRUE;
}
//
// If the delta time is less that the timeout time, then it
// is ok to download their profile (fast enough net connection).
//
if (dwTime < dwSlowTimeOut) {
return TRUE;
}
//
// If the User Preferences states to always use the local
// profile on slow links, then we can exit now with false.
//
if (lpProfile->dwUserPreference == USERINFO_LOCAL_SLOW_LINK) {
lpProfile->dwInternalFlags |= PROFILE_SLOW_LINK;
return FALSE;
}
//
// Display the slow link dialog
//
// If someone sets the dialog box timeout to 0, then we
// don't want to prompt the user. Just force the profile
// to download.
//
if (dwSlowDlgTimeOut > 0) {
bRetVal = DialogBoxParam (g_hDllInstance, MAKEINTRESOURCE(IDD_SLOW_LINK),
NULL, SlowLinkDlgProc, dwSlowDlgTimeOut);
if (!bRetVal) {
lpProfile->dwInternalFlags |= PROFILE_SLOW_LINK;
}
return bRetVal;
}
return TRUE;
}
//*************************************************************
//
// SlowLinkDlgProc()
//
// Purpose: Dialog box procedure for the slow link dialog
//
// Parameters: hDlg - handle to the dialog box
// uMsg - window message
// wParam - wParam
// lParam - lParam
//
// Return: TRUE if message was processed
// FALSE if not
//
// Comments:
//
// History: Date Author Comment
// 2/13/96 ericflo Created
//
//*************************************************************
BOOL APIENTRY SlowLinkDlgProc (HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
TCHAR szBuffer[10];
static DWORD dwSlowLinkTime;
switch (uMsg) {
case WM_INITDIALOG:
CenterWindow (hDlg);
dwSlowLinkTime = (DWORD) lParam;
wsprintf (szBuffer, TEXT("%d"), dwSlowLinkTime);
SetDlgItemText (hDlg, IDC_TIMEOUT, szBuffer);
SetTimer (hDlg, 1, 1000, NULL);
return TRUE;
case WM_TIMER:
if (dwSlowLinkTime >= 1) {
dwSlowLinkTime--;
wsprintf (szBuffer, TEXT("%d"), dwSlowLinkTime);
SetDlgItemText (hDlg, IDC_TIMEOUT, szBuffer);
} else {
//
// Time's up. Download the profile.
//
PostMessage (hDlg, WM_COMMAND, IDC_DOWNLOAD, 0);
}
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_DOWNLOAD:
case IDC_LOCAL:
case IDCANCEL:
//
// Nothing to do. Save the state and return.
//
KillTimer (hDlg, 1);
//
// Return TRUE to download the profile,
// FALSE to use the local profile
//
EndDialog(hDlg, ((LOWORD(wParam) == IDC_LOCAL) ? FALSE : TRUE));
break;
default:
break;
}
break;
}
return FALSE;
}
//*************************************************************
//
// GetUserPreferenceValue()
//
// Purpose: Gets the User Preference flags
//
// Parameters: hToken - User's token
//
// Return: Value
//
// Comments:
//
// History: Date Author Comment
// 2/22/96 ericflo Created
//
//*************************************************************
DWORD GetUserPreferenceValue(HANDLE hToken)
{
TCHAR LocalProfileKey[MAX_PATH];
DWORD RegErr, dwType, dwSize, dwRetVal = USERINFO_UNDEFINED;
LPTSTR lpEnd;
LPTSTR SidString;
HKEY hkeyProfile;
SidString = GetSidString(hToken);
if (SidString != NULL) {
//
// Query for the UserPreference value
//
lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
lpEnd = CheckSlash (LocalProfileKey);
lstrcpy(lpEnd, SidString);
RegErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
LocalProfileKey,
0,
KEY_READ,
&hkeyProfile);
if (RegErr == ERROR_SUCCESS) {
dwSize = sizeof(dwRetVal);
RegQueryValueEx(hkeyProfile,
USER_PREFERENCE,
NULL,
&dwType,
(LPBYTE) &dwRetVal,
&dwSize);
RegCloseKey (hkeyProfile);
}
DeleteSidString(SidString);
}
return dwRetVal;
}
//*************************************************************
//
// ChooseProfileDlgProc()
//
// Purpose: Dialog box procedure for the choose profile dialog
//
// Parameters: hDlg - handle to the dialog box
// uMsg - window message
// wParam - wParam
// lParam - lParam
//
// Return: TRUE if message was processed
// FALSE if not
//
// Comments:
//
// History: Date Author Comment
// 2/23/96 ericflo Created
//
//*************************************************************
BOOL APIENTRY ChooseProfileDlgProc (HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
TCHAR szBuffer[10];
static DWORD dwChooseProfileTime;
switch (uMsg) {
case WM_INITDIALOG:
CenterWindow (hDlg);
dwChooseProfileTime = (DWORD) lParam;
wsprintf (szBuffer, TEXT("%d"), dwChooseProfileTime);
SetDlgItemText (hDlg, IDC_TIMEOUT, szBuffer);
SetTimer (hDlg, 1, 1000, NULL);
return TRUE;
case WM_TIMER:
if (dwChooseProfileTime >= 1) {
dwChooseProfileTime--;
wsprintf (szBuffer, TEXT("%d"), dwChooseProfileTime);
SetDlgItemText (hDlg, IDC_TIMEOUT, szBuffer);
} else {
//
// Time's up. Use the local profile.
//
PostMessage (hDlg, WM_COMMAND, IDC_CP_YES, 0);
}
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_CP_YES:
case IDC_CP_NO:
case IDCANCEL:
//
// Nothing to do. Save the state and return.
//
KillTimer (hDlg, 1);
//
// Return IDYES to use the local profile
// IDNO to download the central profile
//
EndDialog(hDlg, ((LOWORD(wParam) == IDC_CP_NO) ? IDNO : IDYES));
break;
default:
break;
}
break;
}
return FALSE;
}