CPMALError CPIM::unloadProfile(Profile::CProfile *& profile) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__ + (" " + convertIntegerToString((intptr_t)profile))); Profile::IUid piuid; CError err = mInstanceMap.find(profile, piuid); if (!err.isNoError()) { /// @todo what error handling can be here? LOG4CPLUS_INFO(logger, "todo what error handling can be here?"); LOG4CPLUS_ERROR(logger, static_cast<std::string>(err)); return CPMALError(CPMALError::ERROR_WRONG_PARAM, gModuleName); } unloadProfile(piuid, profile); return CPMALError::NoPMALError(gModuleName); }
void CPIM::unloadProfileThroughClient(IProfileManagerCallbacks* clbs, Profile::CProfile* pp, Profile::IUid const& piuid) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__ + ("clbs " + convertIntegerToString((intptr_t)clbs) + " pp " + convertIntegerToString((intptr_t)pp) + " piuid " + piuid.value())); bool reallyUnloaded = false; if (clbs) { // If we have callback to client, we messaging him about died profile clbs->profileDied(pp->getServiceUID(), piuid); reallyUnloaded = !mInstanceMap.isKnown(piuid).isNoError(); } if (!reallyUnloaded) { // We have no callback to client or client not called our // unloadProfile(), so we have to unload this profile manually unloadProfile(piuid, pp); } }
/* returns TRUE if a user profile was unloaded; otherwise, FALSE.*/ BOOL OwnerProfile::unload () { dprintf ( D_FULLDEBUG, "In OwnerProfile::unload()\n" ); priv_state priv = PRIV_UNKNOWN; BOOL profile_unloaded = FALSE, backup_restored = FALSE, ok = FALSE; __try { /* short-cut if we've already unloaded the profile */ if ( !loaded () ) { ok = TRUE; __leave; } /* we must do the following as Condor */ priv = set_condor_priv (); /* Unload the profile */ profile_unloaded = unloadProfile (); if ( !profile_unloaded ) { __leave; } /* make sure to change state with regards to being unloaded, as we cannot _restore_ the original while the profile is loaded */ profile_loaded_ = FALSE; #if 0 /* Now we have unloaded user's profile we can restore the original cached version */ backup_restored = restore (); dprintf ( D_FULLDEBUG, "OwnerProfile::unload: Restoration of %s's " "profile %s.\n", user_name_, backup_restored ? "succeeded" : "failed" ); /* if we were unable to create the backup, we should bail out before we allow the user to make changes to the template profile */ if ( !backup_restored ) { __leave; } #endif /* if we got here, then everything has been reverted */ ok = TRUE; } __finally { /* return to previous privilege level */ set_priv ( priv ); } return ok; }
/* returns TRUE if a user profile was loaded; otherwise, FALSE.*/ BOOL OwnerProfile::load () { dprintf ( D_FULLDEBUG, "In OwnerProfile::load()\n" ); HANDLE have_access = INVALID_HANDLE_VALUE; DWORD last_error = 0, length = 0, i = 0; priv_state priv = PRIV_UNKNOWN; BOOL backup_created = FALSE, profile_loaded = FALSE, profile_exists = FALSE, profile_destroyed = FALSE, ok = FALSE; __try { /* short-cut if we've already loaded the profile */ if ( loaded () ) { ok = TRUE; __leave; } /* we must do the following as Condor */ priv = set_condor_priv (); /* get the user's local profile directory (if this user has a roaming profile, this is when it's cached locally) */ profile_directory_ = directory (); /* if we have have a profile directory, let's make sure that we also have permissions to it. Sometimes, if the startd were to crash, heaven forbid, we may have access to the profile directory, but it may still be locked by the previous login session that was not cleaned up properly (the only resource I know of that the system does not clean up immediately on process termination are user login handles and their resources). */ if ( profile_directory_ ) { dprintf ( D_FULLDEBUG, "OwnerProfile::load: %s's profile directory: '%s'. " "(last-error = %u)\n", user_name_, profile_directory_, GetLastError () ); dprintf ( D_FULLDEBUG, "OwnerProfile::load: A profile directory is listed " "but may not exist.\n" ); have_access = CreateFile ( profile_directory_, GENERIC_WRITE, 0, /* magic # for NOT shared */ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, /* only take a peek */ NULL ); if ( INVALID_HANDLE_VALUE == have_access ) { last_error = GetLastError (); dprintf ( D_FULLDEBUG, "OwnerProfile::load: Failed to access '%s'. " "(last-error = %u)\n", profile_directory_, last_error ); if ( ERROR_ACCESS_DENIED == last_error || ERROR_SHARING_VIOLATION == last_error ) { /************************************************** NOTE: For future implementations which allow for any user to load their profile, what follows bellow is known as a BAD IDEA. We'd prefer to keep all the data, or FAIL! :) **************************************************/ /* so we don't have access, lets just blow it away and create a new one (see bellow) */ profile_destroyed = destroy (); dprintf ( D_FULLDEBUG, "OwnerProfile::load: Destruction of %s's " "profile %s. (last-error = %u)\n", user_name_, profile_destroyed ? "succeeded" : "failed", profile_destroyed ? 0 : GetLastError () ); if ( !profile_destroyed ) { __leave; } } } /* if we're here, then we can access the profile */ profile_exists = TRUE; } /* explicitly create the profile */ if ( !profile_exists ) { dprintf ( D_FULLDEBUG, "OwnerProfile::load: Profile directory does not " "exist, so we're going to create one.\n" ); /* we now create the profile, so we can backup it up directly */ profile_exists = create (); dprintf ( D_FULLDEBUG, "OwnerProfile::load: Creation of profile for %s %s. " "(last-error = %u)\n", user_name_, profile_exists ? "succeeded" : "failed", profile_exists ? 0 : GetLastError () ); /* if the profile still does not exist, then bail */ if ( !profile_exists ) { __leave; } } #if 0 /* now we transfer the user's profile directory to the cache so that we can revert back to it once the user is done doing their thang. */ backup_created = backup (); dprintf ( D_FULLDEBUG, "OwnerProfile::load: Creating a backup of %s's " "profile %s.\n", user_name_, backup_created ? "succeeded" : "failed" ); /* if we were unable to create the backup, we should bail out before we allow the user to make changes to the template profile */ if ( !backup_created ) { __leave; } #endif /* finally, load the user's profile */ profile_loaded = loadProfile (); if ( !profile_loaded ) { __leave; } /* make sure to change state with regards to being loaded */ profile_loaded_ = TRUE; /* everything went as expected */ ok = TRUE; } __finally { /* free the attributes, if required */ if ( !ok && profile_directory_ ) { delete [] profile_directory_; profile_directory_ = NULL; } /* if we loaded the profile, but failed for some other reason, then we should make sure to unload the profile */ if ( !ok && profile_loaded ) { unloadProfile (); } /* return to previous privilege level */ set_priv ( priv ); } return ok; }
/* returns TRUE if a user profile was created; otherwise, FALSE. NOTE: We do not call load() here as we call create() from there, which would be a rather silly loop to be caught it. */ BOOL OwnerProfile::create () { dprintf ( D_FULLDEBUG, "In OwnerProfile::create()\n" ); priv_state priv = PRIV_UNKNOWN; int length = 0; BOOL profile_loaded = FALSE, profile_unloaded = FALSE, profile_deleted = FALSE, ok = FALSE; __try { /* Do the following as condor, since we can't do it as the user, as we are creating the profile for the first time, and we need administrative rights to do this (which, presumably, the "owner" of this profile does not have) */ priv = set_condor_priv (); /* Creating a profile is quite straight forward: simply try to load it. Windows will realize that there isn't one stashed away for the user, so it will creat one for us. We can then simply unload it, since we will be making a copy of the unmodified version of it up at a later point, so that jobs will always run with a clean profile, also thereby eliminating any possible cross job security issues (i.e. writting missleading data to well known registry entries, etc.) */ /* load the user's profile for the first time-- this will effectively create it "for free", using the local "default" account as a template (for various versions of "default", each Windows flavour has it's own naming scheme). */ profile_loaded = loadProfile (); if ( !profile_loaded ) { __leave; } /* now simply unload the profile */ profile_unloaded = unloadProfile (); if ( !profile_unloaded ) { __leave; } /* retrieve the profile's directory */ profile_directory_ = directory (); if ( !profile_directory_ ) { __leave; } /* if we're here, then the profile it ready to be used */ ok = TRUE; } __finally { if ( !ok && ( profile_loaded && !profile_unloaded ) ) { unloadProfile (); } if ( !ok && profile_directory_ ) { delete [] profile_directory_; profile_directory_ = NULL; } /* return to previous privilege level */ set_priv ( priv ); } return ok; }