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.
409 lines
9.2 KiB
409 lines
9.2 KiB
//*************************************************************
|
|
//
|
|
// Copyright (c) Microsoft Corporation 2000-2001
|
|
// All rights reserved
|
|
//
|
|
// conflict.cxx
|
|
//
|
|
//*************************************************************
|
|
|
|
#include "appmgext.hxx"
|
|
|
|
|
|
CConflict::CConflict(
|
|
CAppInfo* pAppInfo,
|
|
CAppInfo* pWinner,
|
|
DWORD dwReason,
|
|
LONG Precedence ) :
|
|
_pAppInfo( pAppInfo ),
|
|
_pwszConflictId( NULL ),
|
|
_Precedence( Precedence ),
|
|
_PrecedenceReason( dwReason ),
|
|
_pWinner( pWinner )
|
|
{}
|
|
|
|
CConflict::~CConflict()
|
|
{
|
|
delete [] _pwszConflictId;
|
|
}
|
|
|
|
HRESULT
|
|
CConflict::Write()
|
|
{
|
|
HRESULT hr;
|
|
|
|
DebugMsg((DM_VERBOSE, IDS_RSOP_LOG_WRITE_INFO, GetApp()->_pwszDeploymentName, GetApp()->_pwszGPOName));
|
|
|
|
hr = SetValue(
|
|
RSOP_ATTRIBUTE_ID,
|
|
_pwszConflictId);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_ID, hr )
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
goto CConflict_Write_cleanup;
|
|
}
|
|
|
|
hr = SetValue(
|
|
RSOP_ATTRIBUTE_PRECEDENCE,
|
|
_Precedence);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_PRECEDENCE, hr )
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
goto CConflict_Write_cleanup;
|
|
}
|
|
|
|
if ( 1 == _Precedence )
|
|
{
|
|
_PrecedenceReason = APP_ATTRIBUTE_REASON_VALUE_WINNING;
|
|
}
|
|
|
|
if ( 0 != _PrecedenceReason )
|
|
{
|
|
hr = SetValue(
|
|
APP_ATTRIBUTE_PRECEDENCE_REASON,
|
|
(LONG) _PrecedenceReason);
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_PRECEDENCE_REASON, hr )
|
|
}
|
|
|
|
if ( 0 != _Precedence )
|
|
{
|
|
if ( _Precedence > 1 || AlreadyExists() )
|
|
{
|
|
GetApp()->_dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE;
|
|
|
|
hr = ClearValue( APP_ATTRIBUTE_APPLY_CAUSE );
|
|
|
|
REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_APPLY_CAUSE, hr )
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetApp()->_dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_NONE;
|
|
}
|
|
|
|
hr = GetApp()->Write( this );
|
|
|
|
CConflict_Write_cleanup:
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CConflict::GetPath( WCHAR* wszPath, DWORD* pchLength )
|
|
{
|
|
//
|
|
// A relative path to an instance of RSOP_ApplicationManagementPolicySetting
|
|
// looks like:
|
|
//
|
|
// RSOP_ApplicationManagementPolicySetting.EntryType=<entrytype>,id="<id-guid>",applicationid="<appid-guid>",precedence=<precedence>
|
|
//
|
|
DWORD cchRequired;
|
|
HRESULT hr = S_OK;
|
|
|
|
ASSERT( ( GetApp()->GetPublicRsopEntryType() <= APP_ATTRIBUTE_ENTRYTYPE_VALUE_ARPLIST_ITEM ) &&
|
|
( GetApp()->GetPublicRsopEntryType() >= APP_ATTRIBUTE_ENTRYTYPE_VALUE_INSTALLED_PACKAGE ) );
|
|
|
|
cchRequired = sizeof( RELATIVE_PATH_FORMAT ) / sizeof( WCHAR ) + // Fixed length portion
|
|
1 + // Entry type
|
|
MAX_SZGUID_LEN * 2 + // 2 guids
|
|
9; // Precedence = 1
|
|
|
|
if ( cchRequired <= *pchLength )
|
|
{
|
|
WCHAR wszDeploymentId[ MAX_SZGUID_LEN ];
|
|
WCHAR* wszApplicationId;
|
|
|
|
LONG lPrecedence;
|
|
LONG EntryType;
|
|
|
|
if ( GetApp()->_bRemovalLogged )
|
|
{
|
|
EntryType = APP_ATTRIBUTE_ENTRYTYPE_VALUE_REMOVED_PACKAGE;
|
|
lPrecedence = 0;
|
|
}
|
|
else
|
|
{
|
|
EntryType = GetApp()->GetPublicRsopEntryType();
|
|
lPrecedence = 1;
|
|
}
|
|
|
|
GuidToString( GetApp()->_DeploymentId, wszDeploymentId);
|
|
|
|
//
|
|
// Since we are only using precedence 1 applications, the application id
|
|
// happens to be the same as the id
|
|
//
|
|
wszApplicationId = wszDeploymentId;
|
|
|
|
hr = StringCchPrintf(
|
|
wszPath,
|
|
*pchLength,
|
|
RELATIVE_PATH_FORMAT,
|
|
EntryType,
|
|
wszDeploymentId,
|
|
wszApplicationId,
|
|
lPrecedence);
|
|
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
else
|
|
{
|
|
*pchLength = cchRequired;
|
|
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CConflict::SetConflictId( WCHAR* pwszConflictId )
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = ERROR_SUCCESS;
|
|
|
|
ASSERT ( ! _pwszConflictId );
|
|
|
|
_pwszConflictId = StringDuplicate( pwszConflictId );
|
|
|
|
if ( ! _pwszConflictId )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
CConflictList::~CConflictList()
|
|
{
|
|
CConflict* pConflict;
|
|
|
|
Reset();
|
|
|
|
for ( Reset(); pConflict = (CConflict*) GetCurrentItem(); )
|
|
{
|
|
MoveNext();
|
|
|
|
pConflict->Remove();
|
|
|
|
delete pConflict;
|
|
}
|
|
}
|
|
|
|
LONG
|
|
CConflictList::AddConflict( CAppInfo* pAppInfo, CAppInfo* pWinner, DWORD dwReason, LONG Precedence )
|
|
{
|
|
CConflict* pNewConflict;
|
|
|
|
pNewConflict = new CConflict( pAppInfo, pWinner, dwReason, Precedence );
|
|
|
|
if ( ! pNewConflict )
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
InsertFIFO( pNewConflict );
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
CConflictTable::CConflictTable() :
|
|
_pLastConflict( NULL )
|
|
{}
|
|
|
|
void
|
|
CConflictTable::Reset()
|
|
{
|
|
_pLastConflict = NULL;
|
|
|
|
_SupersededApps.Reset();
|
|
}
|
|
|
|
|
|
LONG
|
|
CConflictTable::AddConflict(
|
|
CAppInfo* pAppInfo,
|
|
CAppInfo* pWinner,
|
|
DWORD dwReason,
|
|
LONG Prececence )
|
|
{
|
|
return _SupersededApps.AddConflict( pAppInfo, pWinner, dwReason );
|
|
}
|
|
|
|
CConflict*
|
|
CConflictTable::GetNextConflict( LONG* pCurrentPrecedence )
|
|
{
|
|
CConflict* pNextConflict;
|
|
|
|
pNextConflict = NULL;
|
|
|
|
//
|
|
// If we're at the end, leave
|
|
//
|
|
if ( ! _pLastConflict && ! _SupersededApps.GetCurrentItem() )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Try to traverse the last conflict to find the next conflict
|
|
//
|
|
if ( _pLastConflict )
|
|
{
|
|
//
|
|
// The precedence of the next application should be one more
|
|
// than the last conflict
|
|
//
|
|
pNextConflict = _pLastConflict->GetApp()->GetConflictTable()->GetNextConflict( pCurrentPrecedence );
|
|
|
|
if ( pNextConflict )
|
|
{
|
|
(*pCurrentPrecedence)++;
|
|
}
|
|
}
|
|
|
|
if ( ! pNextConflict )
|
|
{
|
|
//
|
|
// If we did not find a conflict as a result of the previous conflict,
|
|
// let's try the next item in our conflict list
|
|
//
|
|
pNextConflict = (CConflict*) ( _SupersededApps.GetCurrentItem() );
|
|
|
|
_SupersededApps.MoveNext();
|
|
|
|
if ( pNextConflict )
|
|
{
|
|
pNextConflict->GetApp()->GetConflictTable()->Reset();
|
|
}
|
|
}
|
|
|
|
_pLastConflict = pNextConflict;
|
|
|
|
//
|
|
// We are finished calculating the precedence and may now
|
|
// set the final precedence value
|
|
//
|
|
if ( pNextConflict )
|
|
{
|
|
pNextConflict->_Precedence = *pCurrentPrecedence;
|
|
}
|
|
|
|
return pNextConflict;
|
|
}
|
|
|
|
LONG
|
|
CConflictTable::GenerateResultantConflictList( CConflictList* pConflictList )
|
|
{
|
|
CConflict* pConflict;
|
|
LONG Status;
|
|
LONG Precedence;
|
|
|
|
Precedence = 2;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
|
|
Reset();
|
|
|
|
while ( pConflict = GetNextConflict( &Precedence ) )
|
|
{
|
|
Status = pConflictList->AddConflict(
|
|
pConflict->GetApp(),
|
|
pConflict->_pWinner,
|
|
pConflict->_PrecedenceReason,
|
|
pConflict->_Precedence);
|
|
|
|
if ( ERROR_SUCCESS != Status )
|
|
break;
|
|
|
|
Precedence = pConflict->_Precedence;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
HRESULT
|
|
CConflict::LogFailure()
|
|
{
|
|
//
|
|
// We only log status for settings
|
|
// with failures
|
|
//
|
|
CAppStatus* pAppStatus;
|
|
|
|
//
|
|
// First, see if this setting (app) has a status
|
|
//
|
|
pAppStatus = (CAppStatus*) GetApp()->_StatusList.GetCurrentItem();
|
|
|
|
if ( ! pAppStatus )
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
//
|
|
// Advance the list to the next failure so
|
|
// that the next caller will log a different failure
|
|
//
|
|
GetApp()->_StatusList.MoveNext();
|
|
|
|
//
|
|
// Skip this status if this is not a failure
|
|
//
|
|
if ( RSOPFailed != pAppStatus->_SettingStatus )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT hr;
|
|
IWbemServices* pWbemServices;
|
|
|
|
//
|
|
// Bind to WMI -- this is essentially no op in policy refresh
|
|
//
|
|
hr = GetApp()->_pManApp->GetRsopContext()->Bind( &pWbemServices );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
POLICYSETTINGSTATUSINFO SettingStatus;
|
|
|
|
memset( &SettingStatus, 0, sizeof( SettingStatus ) );
|
|
|
|
SettingStatus.szEventSource = APPMGMT_EVENT_SOURCE;
|
|
SettingStatus.szEventLogName = L"Application";
|
|
SettingStatus.dwEventID = pAppStatus->_dwEventId;
|
|
SettingStatus.dwErrorCode = ERROR_SUCCESS;
|
|
SettingStatus.status = pAppStatus->_SettingStatus;
|
|
SettingStatus.timeLogged = pAppStatus->_StatusTime;
|
|
|
|
hr = RsopSetPolicySettingStatus(
|
|
0,
|
|
pWbemServices,
|
|
GetRecordInterface(),
|
|
1,
|
|
&SettingStatus);
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
REPORT_ATTRIBUTE_SET_STATUS( L"Policy Setting Status", hr )
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|