📄 locplgmgr.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
// Abstract: Location framework plugin manager
#include <locCore.hpp>
// Global plugin manager
pluginMgr_t * g_pPluginMgr;
//*****************************************************************************
// Init and deinit routines for the location framework
//*****************************************************************************
// Main initialization for the plugin manager.
pluginMgr_t::pluginMgr_t() {
DEBUGCHK(g_pLocLock->IsLocked());
DEBUGCHK(g_serviceState == SERVICE_STATE_STARTING_UP);
m_initSuccess = FALSE;
CReg reg(HKEY_LOCAL_MACHINE,g_rkLocBase);
if (!reg.IsOK()) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Unable to start because base reg key <%s> is not present\r\n",g_rkLocBase));
return;
}
if (! InitProviders(®) ||
! InitResolvers(®) ||
! AssignPluginOrder() ||
! InitReportCollectors())
{
return;
}
m_initSuccess = TRUE;
}
// All pointers are smart pointers and auto-freed, so no work in destructor
pluginMgr_t::~pluginMgr_t() {
DEBUGCHK(g_pLocLock->IsLocked());
DEBUGCHK((g_serviceState != SERVICE_STATE_ON) && (g_serviceState != SERVICE_STATE_STARTING_UP));
}
BOOL pluginMgr_t::IsPlgMgrInited(void) {
return m_initSuccess;
}
// Inserts plugin into the list based on its order. Simple insert algorithm
// since # of plugins will be small.
BOOL pluginMgr_t::InsertPluginOrdered(pluginSmartPtr_t pPlugin) {
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
DWORD newPref = pPlugin->GetPreference();
for (; it != itEnd; ++it) {
if ((*it)->GetPreference() > newPref) {
if (! m_pluginList.insert(it,pPlugin)) {
DEBUGMSG_OOM();
return FALSE;
}
return TRUE;
}
}
if (! m_pluginList.push_back(pPlugin)) {
DEBUGMSG_OOM();
return FALSE;
}
return TRUE;
}
// Now that plugins have been loaded in a sorted list, indicate to
// each one what its load order was. This order will be used later
// when determining when to stop & start plugins after failures.
BOOL pluginMgr_t::AssignPluginOrder(void) {
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
DWORD index = 0;
for (; it != itEnd; ++it) {
(*it)->SetStartOrder(index);
index++;
}
return TRUE;
}
// Read all provider DLL config options, load the DLLs, and get required exports.
BOOL pluginMgr_t::InitProviders(CReg *pBaseReg) {
CReg providersReg(*pBaseReg,g_rkProviders);
WCHAR providerName[MAX_PATH];
DEBUGMSG(ZONE_INIT,(L"LOC: Begin initializing providers...\r\n"));
// Each provider is represented by a reg subkey under ...\Providers
while (providersReg.EnumKey(providerName,SVSUTIL_ARRLEN(providerName))) {
CReg providerReg(providersReg, providerName);
pluginSmartPtr_t pProv = new provider_t(&providerReg,providerName);
if (! pProv.valid()) {
DEBUGMSG_OOM();
return FALSE;
}
if (pProv->GetState() == PLUGIN_STATE_ERROR) {
// This usually indicates plugin misconfiguration (not a fatal OOM)
// Don't put plugin into m_pluginList (so it will be deleted
// automatically) and move on to initialize next plugin.
continue;
}
if (! InsertPluginOrdered(pProv))
return FALSE;
}
DEBUGMSG(ZONE_INIT,(L"LOC: Completed initializing providers...\r\n"));
return TRUE;
}
// Read all resolver DLL config options, load the DLLs, and get required exports.
BOOL pluginMgr_t::InitResolvers(CReg *pBaseReg) {
CReg resolversReg(*pBaseReg,g_rkResolvers);
WCHAR resolverName[MAX_PATH];
DEBUGMSG(ZONE_INIT,(L"LOC: Begin initializing resolvers...\r\n"));
// Each resolver is represented by a reg subkey under ...\resolver
while (resolversReg.EnumKey(resolverName,SVSUTIL_ARRLEN(resolverName))) {
CReg resolverReg(resolversReg, resolverName);
pluginSmartPtr_t pRes = new resolver_t(&resolverReg,resolverName);
if (! pRes.valid()) {
DEBUGMSG_OOM();
return FALSE;
}
if (pRes->GetState() == PLUGIN_STATE_ERROR) {
// This usually indicates plugin misconfiguration (not a fatal OOM)
// Don't put plugin into m_pluginList (so it will be deleted
// automatically) and move on to initialize next plugin.
continue;
}
if (! InsertPluginOrdered(pRes))
return FALSE;
}
DEBUGMSG(ZONE_INIT,(L"LOC: Completed initializing resolver...\r\n"));
return TRUE;
}
// Determines what report types each plugin on the system can generate
// and create a report collector for each unique type.
BOOL pluginMgr_t::InitReportCollectors(void) {
DEBUGMSG(ZONE_REPCOL,(L"LOC: Beginning to initialize reports collectors...\r\n"));
DEBUGCHK(g_pLocLock->IsLocked());
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
//
// Iterate through each plugin on the system.
// For each plugin, create an RC for each report type it
// generates (assuming one hasn't been created already)
//
for (; it != itEnd; ++it) {
GUID generatedReports[MAX_PLUGIN_REPORT_TYPES];
DWORD numRepTypes;
(*it)->GetGeneratedReportInfo(generatedReports,&numRepTypes);
// Iterate through each report type plugin generates
for (DWORD i = 0; i < numRepTypes; i++) {
if (FindRC(&generatedReports[i])) {
// A report collector for this type has already been
// created because another plugin also generates it.
continue;
}
reportColSmartPtr_t pNewReport = new reportCol_t(&generatedReports[i]);
if (! pNewReport.valid()) {
DEBUGMSG_OOM();
return FALSE;
}
if (! m_reportColList.push_back(pNewReport)) {
DEBUGMSG_OOM();
// Auto-deleted because it's a smart pointer going out of scope.
return FALSE;
}
DEBUGMSG(ZONE_REPCOL,(L"LOC: Created report collector for report type <" SVSUTIL_GUID_FORMAT_W L">\r\n",
SVSUTIL_RGUID_ELEMENTS(generatedReports[i])));
}
}
//
// For each resolver on the system, for each report type that it supports
// add it to the appropriate RC's resolver list.
//
for (it = m_pluginList.begin(); it != itEnd; ++it) {
if ((*it)->IsAProvider()) {
// We only care about resolvers.
continue;
}
resolver_t *pRes = (resolver_t*)((plugin_t*)(*it));
GUID supportedReports[MAX_PLUGIN_REPORT_TYPES];
DWORD numSupportedReports;
pRes->GetSupportedReportInfo(supportedReports,&numSupportedReports);
// For each supported report each resolver accepts, find RC (if exists)
// and associate with it.
for (DWORD i = 0; i < numSupportedReports; i++) {
reportCol_t *pRC = FindRC(&supportedReports[i]);
if (NULL == pRC) {
// Just because a resolver supports a report doesn't mean anything
// on the system generates it (and hence no reports collector)
continue;
}
if (ERROR_SUCCESS != pRC->AddToResolversList(pRes))
return FALSE;
}
}
DEBUGMSG(ZONE_REPCOL,(L"LOC: Done initializing reports collectors...\r\n"));
return TRUE;
}
//*****************************************************************************
// Misc plugin manager helper functions
//*****************************************************************************
// Finds reports collector associated with a given GUID
reportCol_t * pluginMgr_t::FindRC(const GUID *pGUID) {
reportColListIter_t it = m_reportColList.begin();
reportColListIter_t itEnd = m_reportColList.end();
for (; it != itEnd; ++it) {
if (0 == memcmp(pGUID,(*it)->GetReportType(),sizeof(GUID)))
return (*it);
}
return NULL;
}
// Helper to find a plugin based on context passed in from a callback
plugin_t *pluginMgr_t::FindPlugin(HANDLE pluginContext) {
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
for (; it != itEnd; ++it) {
if ((*it) == (plugin_t*)pluginContext)
return (*it);
}
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Callback Context <0x%08x> is invalid\r\n",pluginContext));
return NULL;
}
// Returns the plugin that has the specified plugin guid
plugin_t *pluginMgr_t::FindPlugin(const GUID *pPluginGuid) {
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
for (; it != itEnd; ++it) {
if ((*it)->IsGuid(pPluginGuid))
return (*it);
}
return NULL;
}
// This function is called when a plugin has had some fatal error,
// such as throwing an exception. This will call into the plugin itself
// telling it to change its state to PLUGIN_STATE_ERROR and will
// try to load the next plugins for reports this plugin can't generate anymore.
// Once a plugin enters PLUGIN_STATE_ERROR, nothing short of refreshing the LFSVC
// will ever get it out of that state.
void pluginMgr_t::FatalPluginError(plugin_t *pPlugin) {
DEBUGCHK(g_pLocLock->IsLocked());
if (pPlugin->GetState() == PLUGIN_STATE_ERROR) {
// It is possible for this to be called multiple times (i.e. for
// a plugin that throws multiple exceptions). Only take action
// first time plugin gets into this state.
return;
}
DEBUGMSG(ZONE_ERROR,(L"LOC: Plugin <%s> has entered PLUGIN_ERROR_STATE. Trying to start next available plugins\r\n",
pPlugin->GetName()));
pPlugin->SetFatalError();
if (g_serviceState == SERVICE_STATE_ON) {
// If service is on still, then start up next plugins in line.
StartNextPluginsOnFailure(pPlugin);
}
if (pPlugin->IsAResolver()) {
// A failed resolver may have loaded up providers to do work for it.
// Stop any providers that are no longer needed
StopDependentProvidersForResolver((resolver_t*)pPlugin);
}
else {
// If this is last plugin that generated reports for a given resolver,
// indicate the resolver as unavailable now.
ProcessProviderFailureOnResolvers((provider_t*)pPlugin);
}
}
// When an application closes its LocationOpen handle (either via LocationClose call
// or by process shutting-down cleanup), unregister any reports it may have
// forgot to unregister manually.
void pluginMgr_t::UnRegisterEventsFromHandle(locOpenHandle_t *pLocHandle) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -