You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1133 lines
29 KiB
1133 lines
29 KiB
//*************************************************************
|
|
//
|
|
// Copyright (c) Microsoft Corporation 1998
|
|
// All rights reserved
|
|
//
|
|
// Applist.cxx
|
|
//
|
|
//*************************************************************
|
|
|
|
#include "appmgext.hxx"
|
|
|
|
|
|
//
|
|
// CAppList
|
|
//
|
|
|
|
CAppList::CAppList(
|
|
CManagedAppProcessor * pManApp,
|
|
CRsopAppContext * pRsopContext ) :
|
|
_pManApp( pManApp ),
|
|
_bRsopInitialized( FALSE ),
|
|
_hrRsopInit( E_FAIL ),
|
|
_pRsopContext( pRsopContext )
|
|
{}
|
|
|
|
|
|
CAppList::~CAppList()
|
|
{
|
|
CAppInfo * pAppInfo;
|
|
|
|
Reset();
|
|
|
|
while ( pAppInfo = (CAppInfo *) GetCurrentItem() )
|
|
{
|
|
MoveNext();
|
|
|
|
pAppInfo->Remove();
|
|
delete pAppInfo;
|
|
}
|
|
|
|
ResetEnd();
|
|
}
|
|
|
|
DWORD
|
|
CAppList::SetAppActions()
|
|
{
|
|
CAppInfo * pAppInfo;
|
|
DWORD Pass;
|
|
DWORD Status;
|
|
|
|
for ( Pass = 0; Pass <= 5; Pass++ )
|
|
{
|
|
Reset();
|
|
|
|
for (;;)
|
|
{
|
|
pAppInfo = (CAppInfo *) GetCurrentItem();
|
|
|
|
if ( ! pAppInfo )
|
|
break;
|
|
|
|
//
|
|
// Apps get applied from lowest priority to highest priority.
|
|
// Thus if one app fails to apply there is nothing of interest that
|
|
// we can really do. We don't know which lower priority apps
|
|
// may need to be "undone", and we shouldn't abort and thereby
|
|
// prevent higher priority apps from being processed.
|
|
//
|
|
// Therefore, other than logging events, we ignore any errors in
|
|
// the processing and continuing applying all apps.
|
|
//
|
|
|
|
switch ( Pass )
|
|
{
|
|
case 0 :
|
|
Status = pAppInfo->InitializePass0();
|
|
if ( Status != ERROR_SUCCESS )
|
|
return Status;
|
|
break;
|
|
case 1 :
|
|
pAppInfo->SetActionPass1();
|
|
break;
|
|
case 2 :
|
|
pAppInfo->SetActionPass2();
|
|
break;
|
|
case 3 :
|
|
pAppInfo->SetActionPass3();
|
|
break;
|
|
case 4 :
|
|
pAppInfo->SetActionPass4();
|
|
break;
|
|
case 5 :
|
|
if ( pAppInfo->_Status != ERROR_SUCCESS )
|
|
return pAppInfo->_Status;
|
|
break;
|
|
}
|
|
|
|
MoveNext();
|
|
}
|
|
|
|
ResetEnd();
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD
|
|
CAppList::ProcessPolicy()
|
|
{
|
|
CAppInfo * pAppInfo;
|
|
DWORD Pass;
|
|
DWORD Status;
|
|
DWORD FinalStatus;
|
|
HRESULT hr;
|
|
|
|
FinalStatus = ERROR_SUCCESS;
|
|
|
|
Status = _pManApp->Impersonate();
|
|
|
|
if ( ERROR_SUCCESS == Status )
|
|
Status = SetAppActions();
|
|
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// Ensure that we log an event in this case so that RSoP
|
|
// failed view at the extension level has enough information
|
|
// to allow the administrator to diagnose the problem
|
|
//
|
|
gpEvents->PolicyAbort();
|
|
|
|
_pManApp->Revert();
|
|
|
|
_pManApp->GetRsopContext()->SetPolicyAborted( Status );
|
|
|
|
return Status;
|
|
}
|
|
|
|
if ( _pManApp->GetRsopContext()->IsPlanningModeEnabled() )
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
for ( Pass = 0; Pass <= 2; Pass++ )
|
|
{
|
|
for ( Reset();;MoveNext() )
|
|
{
|
|
pAppInfo = (CAppInfo *) GetCurrentItem();
|
|
|
|
if ( ! pAppInfo )
|
|
break;
|
|
|
|
switch ( Pass )
|
|
{
|
|
case 0 :
|
|
Status = pAppInfo->ProcessUnapplyActions();
|
|
break;
|
|
case 1 :
|
|
Status = pAppInfo->ProcessApplyActions();
|
|
break;
|
|
case 2 :
|
|
if ( _pRsopContext->IsRsopEnabled() && _pRsopContext->IsDiagnosticModeEnabled() )
|
|
Status = pAppInfo->ProcessTransformConflicts();
|
|
break;
|
|
}
|
|
|
|
if ( (FinalStatus == ERROR_SUCCESS) && (Status != ERROR_SUCCESS) )
|
|
FinalStatus = Status;
|
|
|
|
//
|
|
// If we are returning an error of some sort, we should force a synchronous
|
|
// refresh if we are not already returning the error to request one. This is
|
|
// needed because some errors require a sync refresh to fix (such as
|
|
// install / uninstall errors), and gp will not give us a sync refresh
|
|
// unless we ask for it.
|
|
//
|
|
if ( ! _pManApp->NoChanges() &&
|
|
( ERROR_SUCCESS != FinalStatus ) &&
|
|
( ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED != FinalStatus ) )
|
|
{
|
|
_pManApp->Revert();
|
|
|
|
(void) ForceSynchronousRefresh( _pManApp->UserToken() );
|
|
|
|
_pManApp->Impersonate();
|
|
}
|
|
}
|
|
|
|
ResetEnd();
|
|
}
|
|
|
|
_pManApp->Revert();
|
|
|
|
return FinalStatus;
|
|
}
|
|
|
|
DWORD
|
|
CAppList::ProcessARPList()
|
|
{
|
|
DWORD Status;
|
|
|
|
Status = _pManApp->Impersonate();
|
|
|
|
if ( ERROR_SUCCESS == Status )
|
|
Status = SetAppActions();
|
|
|
|
_pManApp->Revert();
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CAppList::Count(
|
|
DWORD Flags
|
|
)
|
|
{
|
|
CAppInfo * pAppInfo;
|
|
DWORD Count;
|
|
|
|
Count = 0;
|
|
|
|
Reset();
|
|
|
|
for ( ;; )
|
|
{
|
|
pAppInfo = (CAppInfo *) GetCurrentItem();
|
|
|
|
if ( ! pAppInfo )
|
|
break;
|
|
|
|
if ( pAppInfo->_ActFlags & Flags )
|
|
Count++;
|
|
|
|
MoveNext();
|
|
}
|
|
|
|
ResetEnd();
|
|
|
|
return Count;
|
|
}
|
|
|
|
CAppInfo *
|
|
CAppList::Find(
|
|
GUID DeploymentId
|
|
)
|
|
{
|
|
CAppInfo * pAppInfo;
|
|
|
|
Reset();
|
|
|
|
for (;;)
|
|
{
|
|
pAppInfo = (CAppInfo *) GetCurrentItem();
|
|
|
|
if ( ! pAppInfo )
|
|
break;
|
|
|
|
if ( memcmp( &pAppInfo->_DeploymentId, &DeploymentId, sizeof(GUID) ) == 0 )
|
|
break;
|
|
|
|
MoveNext();
|
|
}
|
|
|
|
ResetEnd();
|
|
|
|
return pAppInfo;
|
|
}
|
|
|
|
HRESULT
|
|
CAppList::WriteLog( DWORD dwFilter )
|
|
{
|
|
CAppInfo * pAppInfo;
|
|
DWORD Status;
|
|
HRESULT hr;
|
|
|
|
hr = InitRsopLog();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if ( ( CRsopAppContext::POLICY_REFRESH == _pRsopContext->GetContext() ) &&
|
|
_pRsopContext->IsDiagnosticModeEnabled() && ! _pManApp->IsRemovingPolicies() )
|
|
{
|
|
hr = PurgeEntries();
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
Reset();
|
|
|
|
for (;;)
|
|
{
|
|
BOOL bLogApp;
|
|
|
|
pAppInfo = (CAppInfo *) GetCurrentItem();
|
|
|
|
if ( ! pAppInfo )
|
|
break;
|
|
|
|
//
|
|
// Check to see if this app is applied to the user and should be logged
|
|
//
|
|
bLogApp = ( RSOP_FILTER_ALL == dwFilter ) ||
|
|
( ( ACTION_UNINSTALL == pAppInfo->Action() ) || ( ACTION_ORPHAN == pAppInfo->Action() ) );
|
|
|
|
//
|
|
// Check to see if this app would have been in the ARP list if not for the
|
|
// fact that the administrator chose to conceal it
|
|
//
|
|
if ( CRsopAppContext::ARPLIST == _pRsopContext->GetContext() )
|
|
{
|
|
if ( ( ACTION_NONE == pAppInfo->Action() ) &&
|
|
( (pAppInfo->_ActFlags & (ACTFLG_Assigned | ACTFLG_Published) ) &&
|
|
!(pAppInfo->_ActFlags & ACTFLG_UserInstall) ) )
|
|
{
|
|
bLogApp = TRUE;
|
|
|
|
pAppInfo->SetAction(
|
|
ACTION_INSTALL,
|
|
0,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
if ( bLogApp )
|
|
{
|
|
hr = WriteAppToRsopLog( pAppInfo );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
MoveNext();
|
|
}
|
|
|
|
ResetEnd();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CAppList::WriteAppToRsopLog( CAppInfo* pAppInfo )
|
|
{
|
|
HRESULT hr;
|
|
CConflict WinningConflict( pAppInfo );
|
|
|
|
//
|
|
// If this is a rolled-back upgrade, the instance
|
|
// is already written and we do not need to do anything
|
|
//
|
|
if ( pAppInfo->_bRollback )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Do not log entries for applications that will be removed
|
|
// in the next sync refresh
|
|
//
|
|
if ( ( ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED == pAppInfo->_Status ) &&
|
|
( ACTION_APPLY != pAppInfo->_Action ) && ( ACTION_INSTALL != pAppInfo->_Action ) &&
|
|
( ACTION_REINSTALL != pAppInfo->_Action ) )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
hr = InitRsopLog();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// If this app failed to be applied, we must log it anyway
|
|
//
|
|
if ( pAppInfo->_StatusList.GetCurrentItem() )
|
|
{
|
|
if ( ACTION_NONE == pAppInfo->Action() )
|
|
{
|
|
pAppInfo->SetAction(
|
|
ACTION_APPLY,
|
|
pAppInfo->_dwApplyCause,
|
|
NULL);
|
|
}
|
|
}
|
|
else if ( _pRsopContext->HasPolicyAborted() )
|
|
{
|
|
//
|
|
// If policy aborted before even trying to apply the app
|
|
// then we shouldn't log this setting unless it has a failure --
|
|
// apps without failures haven't been applied, and apps with
|
|
// failures are known to not apply, so we can safely log those
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
switch ( pAppInfo->GetRsopEntryType() )
|
|
{
|
|
case APP_ATTRIBUTE_ENTRYTYPE_VALUE_INSTALLED_PACKAGE:
|
|
|
|
WCHAR* wszCriteria;
|
|
|
|
wszCriteria = pAppInfo->GetRsopAppCriteria();
|
|
|
|
hr = ClearLog( wszCriteria, TRUE );
|
|
|
|
delete [] wszCriteria;
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// In planning mode, we only apply published apps if they upgrade
|
|
// an assigned app
|
|
//
|
|
if ( _pRsopContext->IsPlanningModeEnabled() )
|
|
{
|
|
if ( ( ACTFLG_Published & pAppInfo->_ActFlags ) && ! pAppInfo->_bSupersedesAssigned )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fall through to the next case
|
|
//
|
|
|
|
case APP_ATTRIBUTE_ENTRYTYPE_VALUE_ARPLIST_ITEM:
|
|
|
|
//
|
|
// In the arplist case, we require the action
|
|
// set to ACTION_INSTALL in order to log the app
|
|
//
|
|
if ( _pManApp->ARPList() &&
|
|
( ACTION_INSTALL != pAppInfo->Action() ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If this is a winning application, create a new entry for the winner
|
|
// and then log its conflicts
|
|
//
|
|
if ( ! pAppInfo->IsSuperseded() )
|
|
{
|
|
WCHAR wszDeploymentId[ MAX_SZGUID_LEN ];
|
|
|
|
pAppInfo->GetDeploymentId( wszDeploymentId);
|
|
|
|
hr = WinningConflict.SetConflictId( wszDeploymentId );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = WriteNewRecord ( &WinningConflict );
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_VERBOSE, IDS_RSOP_LOG_WRITE_FAIL, hr));
|
|
hr = S_OK;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
(void) WinningConflict.LogFailure();
|
|
}
|
|
|
|
(void) WriteConflicts ( pAppInfo );
|
|
}
|
|
break;
|
|
|
|
case APP_ATTRIBUTE_ENTRYTYPE_VALUE_REMOVED_PACKAGE:
|
|
|
|
BOOL bDeleteInstalledEntry;
|
|
CAppStatus* pCurrentStatus;
|
|
|
|
bDeleteInstalledEntry = TRUE;
|
|
|
|
pCurrentStatus = (CAppStatus*) pAppInfo->_StatusList.GetCurrentItem();
|
|
|
|
//
|
|
// Do not delete the installed entry if it was never
|
|
// successfully removed
|
|
//
|
|
if ( pCurrentStatus &&
|
|
( RSOPFailed == pCurrentStatus->_SettingStatus ) )
|
|
{
|
|
bDeleteInstalledEntry = FALSE;
|
|
}
|
|
|
|
//
|
|
// For removed applications, we do not create a new entry,
|
|
// just change the existing entry to indicate that
|
|
// it has been removed
|
|
//
|
|
hr = MarkRSOPEntryAsRemoved(
|
|
pAppInfo,
|
|
bDeleteInstalledEntry);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
pAppInfo->_bRemovalLogged = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CAppList::WriteConflicts( CAppInfo* pAppInfo )
|
|
{
|
|
HRESULT hr;
|
|
CConflictList Conflicts;
|
|
CConflict* pCurrentConflict;
|
|
|
|
hr = pAppInfo->GetConflictTable()->GenerateResultantConflictList( &Conflicts );
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Conflicts.Reset();
|
|
|
|
while ( pCurrentConflict = (CConflict*) Conflicts.GetCurrentItem() )
|
|
{
|
|
WCHAR wszDeploymentId[ MAX_SZGUID_LEN ];
|
|
|
|
pAppInfo->GetDeploymentId( wszDeploymentId);
|
|
|
|
hr = pCurrentConflict->SetConflictId( wszDeploymentId );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
HRESULT hrWrite;
|
|
|
|
if ( ! pCurrentConflict->GetApp()->IsLocal() )
|
|
{
|
|
hrWrite = WriteNewRecord( pCurrentConflict );
|
|
}
|
|
else
|
|
{
|
|
hrWrite = OpenExistingRecord( pCurrentConflict );
|
|
|
|
if ( SUCCEEDED( hrWrite ) )
|
|
{
|
|
hrWrite = pCurrentConflict->Write();
|
|
}
|
|
|
|
if ( SUCCEEDED( hrWrite ) )
|
|
{
|
|
hrWrite = pCurrentConflict->GetApp()->ClearRemovalProperties( pCurrentConflict );
|
|
}
|
|
|
|
if ( SUCCEEDED( hrWrite ) )
|
|
{
|
|
hrWrite = CommitRecord( pCurrentConflict );
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hrWrite ) )
|
|
{
|
|
(void) DeleteStatusRecords( pCurrentConflict );
|
|
}
|
|
|
|
if (FAILED(hrWrite))
|
|
{
|
|
DebugMsg((DM_VERBOSE, IDS_RSOP_LOG_WRITE_FAIL, hrWrite));
|
|
}
|
|
|
|
Conflicts.MoveNext();
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_VERBOSE, IDS_RSOP_CONFLICTS_FAIL, pAppInfo->_pwszDeploymentName, pAppInfo->_pwszGPOName, hr));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAppList::InitRsopLog()
|
|
{
|
|
if ( _bRsopInitialized )
|
|
{
|
|
return _hrRsopInit;
|
|
}
|
|
|
|
_bRsopInitialized = TRUE;
|
|
|
|
_hrRsopInit = InitLog(
|
|
_pRsopContext,
|
|
RSOP_MANAGED_SOFTWARE_APPLICATION);
|
|
|
|
if (FAILED(_hrRsopInit))
|
|
{
|
|
DebugMsg((DM_VERBOSE, IDS_RSOP_LOG_INIT_FAIL, _hrRsopInit));
|
|
return _hrRsopInit;
|
|
}
|
|
|
|
if ( _pRsopContext->Transition() )
|
|
{
|
|
_hrRsopInit = ClearLog( NULL, TRUE );
|
|
}
|
|
else if ( ! _pRsopContext->ForcedRefresh() )
|
|
{
|
|
BOOL bPolicy;
|
|
|
|
bPolicy = FALSE;
|
|
|
|
//
|
|
// In the forced refresh case, we need to preserve the
|
|
// state of policy since it actually has not changed,
|
|
// so we skip the purge below
|
|
//
|
|
|
|
//
|
|
// In the policy refresh case, we need to clear everything
|
|
// that does not apply to the user as well as removal entries
|
|
//
|
|
switch ( _pRsopContext->GetContext() )
|
|
{
|
|
case CRsopAppContext::POLICY_REFRESH:
|
|
|
|
bPolicy = TRUE;
|
|
|
|
if ( ! _pRsopContext->PurgeRemovalEntries() )
|
|
{
|
|
break;
|
|
}
|
|
|
|
_pRsopContext->ResetRemovalPurge();
|
|
|
|
//
|
|
// Purposefully fall through
|
|
//
|
|
|
|
case CRsopAppContext::ARPLIST:
|
|
|
|
_hrRsopInit = ClearLog( GetRsopListCriteria(), bPolicy );
|
|
|
|
if ( FAILED( _hrRsopInit ) )
|
|
{
|
|
DebugMsg((DM_VERBOSE, IDS_RSOP_LOG_INIT_FAIL, _hrRsopInit));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return _hrRsopInit;
|
|
}
|
|
|
|
HRESULT
|
|
CAppList::PurgeEntries()
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = GetEnum( RSOP_PURGE_QUERY );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
HRESULT hrEnum;
|
|
|
|
hrEnum = S_OK;
|
|
|
|
for (;;)
|
|
{
|
|
CPolicyRecord CurrentApplication;
|
|
LONG EntryType;
|
|
|
|
hrEnum = GetNextRecord( &CurrentApplication );
|
|
|
|
if ( S_OK != hrEnum )
|
|
{
|
|
if ( FAILED(hrEnum) )
|
|
{
|
|
hr = hrEnum;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
GUID DeploymentId;
|
|
WCHAR wszDeploymentId[ MAX_SZGUID_LEN ];
|
|
LONG cchSize;
|
|
CAppInfo* pAppliedApp;
|
|
|
|
cchSize = sizeof( wszDeploymentId ) / sizeof( *wszDeploymentId );
|
|
|
|
hrEnum = CurrentApplication.GetValue(
|
|
RSOP_ATTRIBUTE_ID,
|
|
wszDeploymentId,
|
|
&cchSize);
|
|
|
|
if ( FAILED( hrEnum ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( S_OK != hrEnum )
|
|
{
|
|
break;
|
|
}
|
|
|
|
StringToGuid( wszDeploymentId, &DeploymentId );
|
|
|
|
pAppliedApp = Find( DeploymentId );
|
|
|
|
if ( pAppliedApp )
|
|
{
|
|
if ( pAppliedApp->_State & ( APPSTATE_ASSIGNED | APPSTATE_PUBLISHED ) )
|
|
{
|
|
if ( ACTFLG_Published & pAppliedApp->_ActFlags )
|
|
{
|
|
(void) GetUserApplyCause(
|
|
&CurrentApplication,
|
|
pAppliedApp);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if ( ( ACTION_NONE != pAppliedApp->Action() ) ||
|
|
pAppliedApp->_bRollback )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
hrEnum = DeleteRecord( &CurrentApplication, TRUE );
|
|
|
|
if ( FAILED( hrEnum ) )
|
|
{
|
|
hr = hrEnum;
|
|
}
|
|
}
|
|
|
|
FreeEnum();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CAppList::GetUserApplyCause(
|
|
CPolicyRecord* pRecord,
|
|
CAppInfo* pAppInfo
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
LONG ApplyCause;
|
|
|
|
hr = pRecord->GetValue(
|
|
APP_ATTRIBUTE_APPLY_CAUSE,
|
|
&ApplyCause);
|
|
|
|
if ( SUCCEEDED( hr) &&
|
|
( APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE != ApplyCause ) &&
|
|
! pAppInfo->_wszDemandProp )
|
|
{
|
|
pAppInfo->_dwUserApplyCause = ApplyCause;
|
|
|
|
switch ( ApplyCause )
|
|
{
|
|
case APP_ATTRIBUTE_APPLYCAUSE_VALUE_FILEEXT:
|
|
pAppInfo->_wszDemandProp = APP_ATTRIBUTE_ONDEMAND_FILEEXT;
|
|
break;
|
|
|
|
case APP_ATTRIBUTE_APPLYCAUSE_VALUE_CLSID:
|
|
pAppInfo->_wszDemandProp = APP_ATTRIBUTE_ONDEMAND_CLSID;
|
|
break;
|
|
|
|
case APP_ATTRIBUTE_APPLYCAUSE_VALUE_PROGID:
|
|
pAppInfo->_wszDemandProp = APP_ATTRIBUTE_ONDEMAND_PROGID;
|
|
break;
|
|
|
|
default:
|
|
pAppInfo->_wszDemandProp = NULL;
|
|
break;
|
|
}
|
|
|
|
if ( pAppInfo->_wszDemandProp && ! pAppInfo->_wszDemandSpec )
|
|
{
|
|
LONG cchSize;
|
|
|
|
cchSize = 0;
|
|
|
|
hr = pRecord->GetValue(
|
|
pAppInfo->_wszDemandProp,
|
|
pAppInfo->_wszDemandSpec,
|
|
&cchSize);
|
|
|
|
if ( S_FALSE == hr )
|
|
{
|
|
pAppInfo->_wszDemandSpec = new WCHAR [ cchSize ];
|
|
|
|
if ( pAppInfo->_wszDemandSpec )
|
|
{
|
|
hr = pRecord->GetValue(
|
|
pAppInfo->_wszDemandProp,
|
|
pAppInfo->_wszDemandSpec,
|
|
&cchSize);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAppList::MarkRSOPEntryAsRemoved(
|
|
CAppInfo* pAppInfo,
|
|
BOOL bRemoveInstances)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR* wszRemovalCriteria;
|
|
|
|
wszRemovalCriteria = NULL;
|
|
|
|
DebugMsg((DM_VERBOSE, IDS_RSOP_LOG_WRITE_INFO, pAppInfo->_pwszDeploymentName, pAppInfo->_pwszGPOName));
|
|
|
|
//
|
|
// If this is a removed app that was reapplied as part of upgrade rollback,
|
|
// we do not want to remove the instances
|
|
//
|
|
if ( pAppInfo->_bRollback )
|
|
{
|
|
bRemoveInstances = FALSE;
|
|
}
|
|
|
|
//
|
|
// Set up this list's rsop enumerator to enumerate instances of this application
|
|
//
|
|
hr = FindRsopAppEntry(
|
|
pAppInfo,
|
|
&wszRemovalCriteria );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
for (;;)
|
|
{
|
|
CConflict RemovedApplication( pAppInfo );
|
|
LONG Precedence;
|
|
|
|
hr = GetNextRecord( &RemovedApplication );
|
|
|
|
if ( S_OK != hr )
|
|
{
|
|
break;
|
|
}
|
|
|
|
hr = RemovedApplication.GetValue(
|
|
RSOP_ATTRIBUTE_PRECEDENCE,
|
|
&Precedence);
|
|
|
|
if ( FAILED (hr) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If this is a removal of an assigned application, then we should
|
|
// change the apply cause of the installed application to assigned
|
|
// rather than user
|
|
//
|
|
if ( 1 == Precedence )
|
|
{
|
|
if ( ( pAppInfo->_State & APPSTATE_ASSIGNED ) &&
|
|
( CRsopAppContext::REMOVAL == _pRsopContext->GetContext() ) )
|
|
{
|
|
LONG CurrentApplyCause;
|
|
LONG CurrentEligibility;
|
|
|
|
//
|
|
// First, we must find out the current apply cause so
|
|
// that we can propagate that to the removal entry
|
|
//
|
|
hr = RemovedApplication.GetValue(
|
|
APP_ATTRIBUTE_APPLY_CAUSE,
|
|
&CurrentApplyCause);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = RemovedApplication.GetValue(
|
|
APP_ATTRIBUTE_ELIGIBILITY,
|
|
&CurrentEligibility);
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// Now set the current apply cause to assigned
|
|
//
|
|
hr = RemovedApplication.SetValue(
|
|
APP_ATTRIBUTE_APPLY_CAUSE,
|
|
APP_ATTRIBUTE_APPLYCAUSE_VALUE_ASSIGNED);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_APPLY_CAUSE, hr );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// Also set the eligibility to assigned
|
|
//
|
|
hr = RemovedApplication.SetValue(
|
|
APP_ATTRIBUTE_ELIGIBILITY,
|
|
APP_ATTRIBUTE_ELIGIBILITY_VALUE_ASSIGNED);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ELIGIBILITY, hr );
|
|
}
|
|
|
|
//
|
|
// Clear out any attributes that should not be set for applications
|
|
// applied due to assignment
|
|
//
|
|
hr = RemovedApplication.ClearValue(
|
|
APP_ATTRIBUTE_ONDEMAND_FILEEXT);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ONDEMAND_FILEEXT, hr )
|
|
|
|
hr = RemovedApplication.ClearValue(
|
|
APP_ATTRIBUTE_ONDEMAND_CLSID);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ONDEMAND_CLSID, hr )
|
|
|
|
hr = RemovedApplication.ClearValue(
|
|
APP_ATTRIBUTE_ONDEMAND_PROGID);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ONDEMAND_PROGID, hr )
|
|
}
|
|
|
|
//
|
|
// Commit the record for the installed application
|
|
//
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = CommitRecord( &RemovedApplication );
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// Now set the removal entry's install cause to
|
|
// that of the original install
|
|
//
|
|
hr = RemovedApplication.SetValue(
|
|
APP_ATTRIBUTE_APPLY_CAUSE,
|
|
CurrentApplyCause);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_APPLY_CAUSE, hr );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// Also set the eligibility to assigned
|
|
//
|
|
hr = RemovedApplication.SetValue(
|
|
APP_ATTRIBUTE_ELIGIBILITY,
|
|
CurrentEligibility);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ELIGIBILITY, hr );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// We must mark the highest precedence entry
|
|
// (the currently applied entry) as removed --
|
|
// see if this has the highest precedence (1)
|
|
//
|
|
if ( bRemoveInstances &&
|
|
( ( pAppInfo->_State & APPSTATE_PUBLISHED ) ||
|
|
( CRsopAppContext::POLICY_REFRESH != _pRsopContext->GetContext() ) ) )
|
|
{
|
|
hr = DeleteRecord ( &RemovedApplication, TRUE );
|
|
}
|
|
else
|
|
{
|
|
hr = DeleteStatusRecords( &RemovedApplication );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = RemovedApplication.SetValue(
|
|
APP_ATTRIBUTE_ENTRYTYPE,
|
|
APP_ATTRIBUTE_ENTRYTYPE_VALUE_REMOVED_PACKAGE);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ENTRYTYPE, hr );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = RemovedApplication.SetValue(
|
|
RSOP_ATTRIBUTE_PRECEDENCE,
|
|
0L);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_PRECEDENCE, hr );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pAppInfo->WriteRemovalProperties( &RemovedApplication );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = CommitRecord( &RemovedApplication );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
(void) DeleteStatusRecords( &RemovedApplication );
|
|
(void) RemovedApplication.LogFailure();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = DeleteRecord ( &RemovedApplication, TRUE );
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
FreeEnum();
|
|
|
|
if ( bRemoveInstances &&
|
|
SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// We've already found the highest precedence entry
|
|
// and copied it as a removal entry --
|
|
// if the caller specified to remove the original
|
|
// instances for this app's conflict id, do so
|
|
//
|
|
hr = ClearLog( wszRemovalCriteria, TRUE );
|
|
}
|
|
|
|
delete [] wszRemovalCriteria;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CAppList::FindRsopAppEntry(
|
|
CAppInfo* pAppInfo,
|
|
WCHAR** ppwszAppCriteria )
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = InitRsopLog();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
*ppwszAppCriteria = pAppInfo->GetRsopAppCriteria();
|
|
|
|
if ( *ppwszAppCriteria )
|
|
{
|
|
hr = GetEnum( *ppwszAppCriteria );
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
delete [] *ppwszAppCriteria;
|
|
*ppwszAppCriteria = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
WCHAR*
|
|
CAppList::GetRsopListCriteria()
|
|
{
|
|
WCHAR* wszCriteria;
|
|
|
|
switch ( _pRsopContext->GetContext() )
|
|
{
|
|
case CRsopAppContext::ARPLIST:
|
|
wszCriteria = RSOP_ARP_CONTEXT_QUERY;
|
|
break;
|
|
|
|
case CRsopAppContext::POLICY_REFRESH:
|
|
wszCriteria = RSOP_POLICY_CONTEXT_QUERY;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
return wszCriteria;
|
|
}
|
|
|
|
|
|
|
|
|
|
|