Leaked source code of windows server 2003
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.
 
 
 
 
 
 

438 lines
11 KiB

//*************************************************************
//
// Copyright (c) Microsoft Corporation 1998
// All rights reserved
//
// appmgext.cxx
//
//*************************************************************
#include "appmgext.hxx"
BOOL gbInitialized = FALSE;
HINSTANCE ghInst = NULL;
extern "C" DWORD WINAPI
ProcessGroupPolicyObjectsEx(
IN DWORD dwFlags,
IN HANDLE hUserToken,
IN HKEY hKeyRoot,
IN PGROUP_POLICY_OBJECT pDeletedGPOList,
IN PGROUP_POLICY_OBJECT pChangedGPOList,
IN ASYNCCOMPLETIONHANDLE pHandle,
IN BOOL *pbAbort,
IN PFNSTATUSMESSAGECALLBACK pfnStatusCallback,
IN IWbemServices *pWbemServices,
OUT HRESULT *phrRsopStatus
)
{
DWORD Status;
*phrRsopStatus = S_OK;
Status = ERROR_SUCCESS;
//
// It is not appropriate for appmgmt to function in safe mode --
// detect this case and exit if we are in safe mode
//
if ( dwFlags & GPO_INFO_FLAG_SAFEMODE_BOOT )
return ERROR_GEN_FAILURE;
if ( ! gbInitialized )
Initialize();
InitDebugSupport( DEBUGMODE_POLICY );
CreatePolicyEvents();
if ( dwFlags & GPO_INFO_FLAG_VERBOSE )
gDebugLevel |= DL_VERBOSE | DL_EVENTLOG;
ConditionalBreakIntoDebugger();
//
// Before NT 5.1, appmgmt was never applied in the background. Starting
// with NT 5.1 however, it gets called for background refresh when asynchronous
// foreground refreshes are enabled so that it can detect the need for a synchronous refresh.
//
// Normally, it will not be called for a slow link, but that behavior
// can be modified by policy on group policy.
//
//
// Note that during the asynchronous foreground refresh, the background refresh flag is
// also set in order to maintain compatibility with earlier extensions, so when detecting
// a true background refresh case below, we need to make sure the asynchronous foreground flag
// is not enabled
//
if ( ( dwFlags & GPO_INFO_FLAG_BACKGROUND ) && ! ( dwFlags & GPO_INFO_FLAG_ASYNC_FOREGROUND ) )
{
DebugMsg((DM_VERBOSE, IDS_BACKGROUND_REFRESH));
//
// For background refreshes, we will notify the policy engine that we
// need to be called in the synchronous foreground refresh if there are changes
//
if ( ! ( dwFlags & GPO_INFO_FLAG_NOCHANGES ) )
{
DebugMsg((DM_VERBOSE, IDS_CHANGES_DETECTED));
Status = ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED;
}
DebugMsg((DM_VERBOSE, IDS_PROCESSGPT_RETURN, Status));
return Status;
}
gpEvents->SetToken( hUserToken );
LogTime();
SignalPolicyStart( ! (dwFlags & GPO_INFO_FLAG_MACHINE) );
CRsopAppContext DiagnosticModeContext(
pWbemServices,
( dwFlags & GPO_INFO_FLAG_LOGRSOP_TRANSITION ) && ! ( dwFlags & GPO_INFO_FLAG_ASYNC_FOREGROUND ),
phrRsopStatus );
if ( pDeletedGPOList )
{
DiagnosticModeContext.SetGPOAppRemoval();
Status = ProcessGPOList(
pDeletedGPOList,
dwFlags,
hUserToken,
hKeyRoot,
pfnStatusCallback,
PROCESSGPOLIST_DELETED,
&DiagnosticModeContext
);
}
if ( pChangedGPOList && (ERROR_SUCCESS == Status) )
{
DiagnosticModeContext.SetGPOAppAdd();
Status = ProcessGPOList(
pChangedGPOList,
dwFlags,
hUserToken,
hKeyRoot,
pfnStatusCallback,
PROCESSGPOLIST_CHANGED,
&DiagnosticModeContext);
}
DebugMsg((DM_VERBOSE, IDS_PROCESSGPT_RETURN, Status));
SignalPolicyEnd( ! (dwFlags & GPO_INFO_FLAG_MACHINE) );
gpEvents->ClearToken();
return Status;
}
DWORD
ProcessGPOList(
PGROUP_POLICY_OBJECT pGPOList,
DWORD dwFlags,
HANDLE hUserToken,
HKEY hKeyRoot,
PFNSTATUSMESSAGECALLBACK pfnStatusCallback,
DWORD dwListType,
CRsopAppContext* pRsopContext
)
{
CManagedAppProcessor * pManApps;
PGROUP_POLICY_OBJECT pCurrentGPO;
DWORD Status;
BOOL bDeletedGPOs;
//
// In reporting mode, we need to dump all the apps --
// here, we are computing resultant set, which is much different
// than dumping the contents -- we will simply exit
// successfully and instead allow the ARP planning simulation
// to dump the list of apps
//
if ( pRsopContext->IsReportingModeEnabled() )
{
return STATUS_SUCCESS;
}
CLoadMsi LoadMsi( Status );
if ( Status != ERROR_SUCCESS )
return Status;
Status = ERROR_OUTOFMEMORY;
bDeletedGPOs = (PROCESSGPOLIST_DELETED == dwListType);
pManApps = new CManagedAppProcessor(
dwFlags,
hUserToken,
hKeyRoot,
pfnStatusCallback,
FALSE,
! bDeletedGPOs,
pRsopContext,
Status);
if ( ERROR_SUCCESS != Status )
{
if ( pManApps )
delete pManApps;
pManApps = 0;
}
if ( ! pManApps )
return Status;
if ( bDeletedGPOs )
{
DebugMsg((DM_VERBOSE, IDS_POLICY_REMOVED, dwFlags));
}
else
{
DebugMsg((DM_VERBOSE, IDS_POLICY_APPLY, dwFlags));
}
Status = pManApps->SetPolicyListFromGPOList( pGPOList );
if ( ERROR_SUCCESS != Status )
return Status;
if ( bDeletedGPOs )
Status = pManApps->Delete();
else
Status = pManApps->Process();
//
// Write any Rsop logs -- this is a no op if
// rsop logging is not enabled
//
pManApps->WriteRsopLogs();
if ( ! pManApps->NoChanges() &&
((Status != ERROR_SUCCESS) || ! bDeletedGPOs) )
{
gpEvents->PolicyStatus( Status, pManApps->ErrorReason() );
}
if ( ! pManApps->GetRsopContext()->PurgeRemovalEntries() )
{
pRsopContext->ResetRemovalPurge();
}
HRESULT hrRsopStatus;
hrRsopStatus = pManApps->GetRsopContext()->GetRsopStatus();
if ( FAILED( hrRsopStatus ) )
{
gpEvents->RsopLoggingStatus( hrRsopStatus );
}
delete pManApps;
return Status;
}
extern "C" BOOL WINAPI
DllMain(
HINSTANCE hInstance,
DWORD dwReason,
LPVOID lpReserved
)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH :
ghDllInstance = hInstance;
gSystemLangId = GetSystemDefaultLangID();
DisableThreadLibraryCalls(hInstance);
InitDebugSupport( DEBUGMODE_CLIENT );
InitializeClassStore(FALSE);
//
// Init our event logging -- this is used
// by both server and cstore subcomponents
//
gpEvents = new CEvents();
if (!gpEvents)
return FALSE;
break;
case DLL_PROCESS_DETACH :
Uninitialize();
break;
}
return TRUE;
}
void
Initialize()
{
ghInst = LoadLibrary( L"appmgmts.dll" );
gbInitialized = ghInst != NULL;
}
extern "C" DWORD WINAPI
GenerateGroupPolicy(
IN DWORD dwFlags,
IN BOOL *pbAbort,
IN WCHAR *pwszSite,
IN PRSOP_TARGET pComputerTarget,
IN PRSOP_TARGET pUserTarget )
{
DWORD Status;
Status = ERROR_SUCCESS;
if ( ! gbInitialized )
Initialize();
InitDebugSupport( DEBUGMODE_POLICY );
if ( dwFlags & GPO_INFO_FLAG_VERBOSE )
gDebugLevel |= DL_VERBOSE | DL_EVENTLOG;
ConditionalBreakIntoDebugger();
LogTime();
if ( pComputerTarget && pComputerTarget->pGPOList )
{
CRsopAppContext MachinePlanningModeContext(
pComputerTarget,
dwFlags & GPO_INFO_FLAG_REPORT
);
Status = ProcessGPOList(
pComputerTarget->pGPOList,
dwFlags,
NULL,
NULL,
NULL,
PROCESSGPOLIST_CHANGED,
&MachinePlanningModeContext);
if ( ( ERROR_SUCCESS == Status ) &&
( dwFlags & GPO_INFO_FLAG_REPORT ) )
{
CRsopAppContext MachineReportingModeContext( pComputerTarget, TRUE );
Status = GenerateManagedApplications(
pComputerTarget->pGPOList,
dwFlags,
&MachineReportingModeContext);
}
}
if ( pUserTarget && pUserTarget->pGPOList )
{
CRsopAppContext UserPlanningModeContext(
pUserTarget,
dwFlags & GPO_INFO_FLAG_REPORT
);
Status = ProcessGPOList(
pUserTarget->pGPOList,
dwFlags,
NULL,
NULL,
NULL,
PROCESSGPOLIST_CHANGED,
&UserPlanningModeContext);
if ( ERROR_SUCCESS == Status )
{
CRsopAppContext UserPlanningModeARPContext( pUserTarget, dwFlags & GPO_INFO_FLAG_REPORT );
Status = GenerateManagedApplications(
pUserTarget->pGPOList,
dwFlags,
&UserPlanningModeARPContext);
}
}
//
// In planning mode, Need to undo the extra reference count
// that normally occurs in regular policy execution mode.
//
if ( ghInst )
{
FreeLibrary( ghInst );
}
DebugMsg((DM_VERBOSE, IDS_PROCESSGPT_RETURN, Status));
return Status;
}
DWORD
GenerateManagedApplications(
PGROUP_POLICY_OBJECT pGPOList,
DWORD dwFlags,
CRsopAppContext* pRsopContext
)
{
DWORD Status;
HRESULT hr;
hr = pRsopContext->SetARPContext();
if ( FAILED(hr) )
{
return ERROR_INVALID_PARAMETER;
}
CManagedAppProcessor ApplicationProcessor(
dwFlags,
NULL,
NULL,
NULL,
TRUE,
FALSE,
pRsopContext,
Status);
if ( ERROR_SUCCESS == Status )
{
Status = ApplicationProcessor.SetPolicyListFromGPOList(
pGPOList);
if ( ERROR_SUCCESS == Status )
{
Status = ApplicationProcessor.GetManagedApplications(
NULL,
NULL);
}
}
return Status;
}