📄 locplgmgr.cpp
字号:
pRes->ReportTypeAvailable(pNewReportType);
if (pRC->NewReport(pRes,pNewReport))
pRC->PluginStateChange();
if (oldStateReport == PLUGIN_STATE_UNAVAILABLE) {
// In this case, the plugin was temporarily unavailable for this
// report type (not necessarily others) and lower priority plugins may have
// been started for this type. Stop them.
StopPluginsForReportType(pNewReportType, pRes->GetStartOrder() + 1);
}
err = ERROR_SUCCESS;
done:
g_pLocLock->Unlock();
return err;
}
// Called when a resolver cannot generate the resolved report. Note
// that resolvers do not call this function directly, but instead the LF
// will have it called when a resolver returns from a resolution without
// resolving a particular report type
DWORD pluginMgr_t::ResolverReportTypeUnavailable(resolver_t *pRes, const GUID *pReportType) {
DEBUGMSG(ZONE_RESOLVER,(L"LOC: ResolverUnavailable for resolver DLL <%s>",
pRes->GetName()));
// LF itself (not a 3rd party plugin) is calling this, so we can assume
// that reportType is reasonably well formatted.
DEBUGCHK(g_pLocLock->IsLocked());
DEBUGCHK(pReportType);
DEBUGCHK(g_serviceState == SERVICE_STATE_ON);
DEBUGCHK(FindResolver(pRes));
DWORD err;
PLUGIN_STATE oldReportState = pRes->GetReportTypeState(pReportType);
if (oldReportState <= PLUGIN_STATE_UNAVAILABLE) {
// In this case, resolver has already been put into the unavailable
// state. The resolver is basically calling unavaibale a 2nd time
// (before giving new data) and hence we ignore this report.
DEBUGMSG(ZONE_RESOLVER,(L"LOC: Ignoring Resolver Unavialable for <%s> because state is off/error/unavail\r\n",
pRes->GetName()));
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
pRes->ReportTypeUnavailable(pReportType);
// Determines whether any report type in resolver is still active
PLUGIN_STATE currentState = pRes->GetState();
// Current state goes to unavilable if NO reports this resolver generates
// can be resolved at this point
if (currentState == PLUGIN_STATE_UNAVAILABLE) {
// It doesn't matter if plugin was on or just starting up at this point -
// either way we need to try to start next plugin in line.
StartNextPluginsOnFailure(pRes);
// Stop providers if they were only spun up for this report
StopDependentProvidersForResolver(pRes);
}
err = ERROR_SUCCESS;
done:
return err;
}
//*****************************************************************************
// Routines that process Location Framework API calls.
//*****************************************************************************
// An application has indicated via LocationRegisterForReport that it wants
// plugin(s) needed to generate this report started.
DWORD pluginMgr_t::RegisterAppForReport(const GUID *pReportType, locOpenHandle_t *pLocHandle,
HANDLE hNewLocationReport, HANDLE hStateChangeEvent)
{
DEBUGCHK(g_pLocLock->IsLocked());
reportCol_t *pRC = FindRC(pReportType);
if (! pRC) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: No plugin supports report type <" SVSUTIL_GUID_FORMAT_W L">\r\n",
SVSUTIL_PGUID_ELEMENTS(pReportType)));
return ERROR_DEV_NOT_EXIST;
}
PLUGIN_STATE reportState = GetPluginInfoForReport(pReportType, NULL,FALSE);
if (reportState == PLUGIN_STATE_ERROR) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: All plugins that support report type <" SVSUTIL_GUID_FORMAT_W L"> are in PLUGIN_ERROR state\r\n",
SVSUTIL_PGUID_ELEMENTS(pReportType)));
return ERROR_DEV_NOT_EXIST;
}
if (pRC->HasRegisteredAppsOrResolvers()) {
// Another application has already registered for this report type
// The plugin manager has already started appropriate plugins to process
// this, so just note that there's a new client requesting reports.
return pRC->RegisterAppForReport(pLocHandle, hNewLocationReport, hStateChangeEvent);
}
// Otherwise, this is first instance of anything registering for this report type.
// Register now, even though we don't know if we'll succeed, so that if we hit
// an OOM here we don't bother starting up plugin manager
DWORD err = pRC->RegisterAppForReport(pLocHandle, hNewLocationReport, hStateChangeEvent);
if (err != ERROR_SUCCESS)
return err;
err = StartPluginForReportType(pReportType,0);
if (err == ERROR_SUCCESS)
return ERROR_SUCCESS;
// StartPluginForReportType could fail if for instance a resolver
// was only plugin that supported this type, but the resolver
// couldn't startup any providers that it required.
DEBUGMSG(ZONE_ERROR,(L"LOC: No plugins were available to service report type <" SVSUTIL_GUID_FORMAT_W L">",
SVSUTIL_PGUID_ELEMENTS(pReportType)));
// Cleanup
pRC->UnRegisterAppForReport(pLocHandle);
return ERROR_DEV_NOT_EXIST;
}
// An application no longer wishes to the particular report type to be
// active. Deregister and potentially close plugins that were generating
// the report.
DWORD pluginMgr_t::UnRegisterAppForReport(locOpenHandle_t *pLocHandle, const GUID *pReportType) {
reportCol_t *pRC = FindRC(pReportType);
if (! pRC) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: No plugin supports report type <" SVSUTIL_GUID_FORMAT_W L">\r\n",
SVSUTIL_PGUID_ELEMENTS(pReportType)));
return ERROR_DEV_NOT_EXIST;
}
DWORD err = pRC->UnRegisterAppForReport(pLocHandle);
if (err != ERROR_SUCCESS)
return err;
if (pRC->HasRegisteredAppsOrResolvers()) {
// If this report has other applications or resolvers
// registered on it, then we take no further action
return ERROR_SUCCESS;
}
// No longer require this report type, so tell plugins generating it to stop.
StopPluginsForReportType(pReportType, 0);
return ERROR_SUCCESS;
}
// Fill in fields of LOCATION_SERVICE_STATE
void pluginMgr_t::GetServiceState(LOCATION_SERVICE_STATE *pServiceState) {
DEBUGCHK(g_pLocLock->IsLocked());
pServiceState->serviceState = g_serviceState;
pServiceState->numLoadedProviders = pServiceState->numLoadedResolvers =
pServiceState->numActiveProviders = pServiceState->numActiveResolvers = 0;
// Iterate through each plugin, incrementing count and examining state.
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
for (; it != itEnd; ++it) {
PLUGIN_STATE pluginState = (*it)->GetState();
BOOL isActive = (pluginState >= PLUGIN_STATE_STARTING_UP);
if ((*it)->IsAProvider()) {
pServiceState->numLoadedProviders++;
if (isActive)
pServiceState->numActiveProviders++;
}
else {
DEBUGCHK((*it)->IsAResolver());
pServiceState->numLoadedResolvers++;
if (isActive)
pServiceState->numActiveResolvers++;
}
}
}
// Retrieves information about all providers loaded on the system,
// as the result of LocationGetProvidersInfo call
DWORD pluginMgr_t::GetProvidersInfo(PROVIDER_INFORMATION *pProviders, DWORD *pcbBuffer) {
DEBUGCHK(g_pLocLock->IsLocked());
//
// Determine if passed buffer is big enough
//
LOCATION_SERVICE_STATE locServiceState;
GetServiceState(&locServiceState);
DWORD numBytesToWrite = locServiceState.numLoadedProviders*sizeof(PROVIDER_INFORMATION);
if ((*pcbBuffer) < numBytesToWrite) {
#ifdef DEBUG
if ((*pcbBuffer) != 0) {
// if app passed 0 bytes, they're expecting an error so don't DEBUGMSG
DEBUGMSG(ZONE_ERROR,(L"LOC: LocationGetProvidersInfo passed <%d> byte buffer size but needs <%d> bytes\r\n",
*pcbBuffer,numBytesToWrite));
}
#endif
*pcbBuffer = numBytesToWrite;
return ERROR_INSUFFICIENT_BUFFER;
}
*pcbBuffer = numBytesToWrite;
//
// Actually retrieve the data into the buffer
//
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
for (; it != itEnd; ++it) {
if ((*it)->IsAResolver())
continue;
provider_t *pProv = (provider_t*)((plugin_t*)(*it));
pProv->GetProviderInfo(pProviders);
pProviders++;
}
return ERROR_SUCCESS;
}
// Retrieves information about all resolvers loaded on the system,
// as the result of LocationGetResolversInfo call
DWORD pluginMgr_t::GetResolversInfo(RESOLVER_INFORMATION *pResolvers, DWORD *pcbBuffer) {
DEBUGCHK(g_pLocLock->IsLocked());
//
// Determine if passed buffer is big enough
//
LOCATION_SERVICE_STATE locServiceState;
GetServiceState(&locServiceState);
DWORD numBytesToWrite = locServiceState.numLoadedResolvers*sizeof(RESOLVER_INFORMATION);
if ((*pcbBuffer) < numBytesToWrite) {
#ifdef DEBUG
if ((*pcbBuffer) != 0) {
// if app passed 0 bytes, they're expecting an error so don't DEBUGMSG
DEBUGMSG(ZONE_ERROR,(L"LOC: LocationGetResolversInfo passed <%d> byte buffer size but needs <%d> bytes\r\n",
*pcbBuffer,numBytesToWrite));
}
#endif
*pcbBuffer = numBytesToWrite;
return ERROR_INSUFFICIENT_BUFFER;
}
*pcbBuffer = numBytesToWrite;
//
// Actually retrieve the data into the buffer
//
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
for (; it != itEnd; ++it) {
if ((*it)->IsAProvider())
continue;
resolver_t *pRes = (resolver_t*)((plugin_t*)(*it));
pRes->GetResolverInfo(pResolvers);
pResolvers++;
}
return ERROR_SUCCESS;
}
// Determines state of the plugin that can generate the given report,
// if the system supports it. Since multiple plugins may be able to support
// the same report type, we return the "highest" state (based on int value
// of the PLUGIN_STATE enum). This means if highest prio plugin is in ERROR
// state, next is UNAVAILABLE, 3rd is starting up, and 4th is OFF, we
// chose the starting up.
PLUGIN_STATE pluginMgr_t::GetPluginInfoForReport(const GUID *pReportType, GUID *pPluginGuid, BOOL providersOnly) {
DEBUGCHK(g_pLocLock->IsLocked());
PLUGIN_STATE retState = PLUGIN_STATE_NOT_SUPPORTED;
const GUID *pCurPlugin = NULL;
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
for (; it != itEnd; ++it) {
if (! (*it)->CanGenerateReportType(pReportType))
continue;
if (providersOnly && (*it)->IsAResolver())
continue;
PLUGIN_STATE pluginState = (*it)->GetReportTypeState(pReportType);
if (pluginState > retState) {
pCurPlugin = (*it)->GetGuid();
retState = pluginState;
}
}
if (pPluginGuid) {
if (pCurPlugin)
memcpy(pPluginGuid,pCurPlugin,sizeof(GUID));
else
memset(pPluginGuid,0,sizeof(GUID));
}
return retState;
}
#ifdef DEBUG
// Verify that every item on the pluginList is unique. At various
// times LF creates such lists and assumes that the list has only
// unique items on it. Failing this check indicates a serious bug in the LF
// that could cause plugins to be called multiple times for the same event.
void DbgVerifyPluginListItemsUnique(pluginList_t *pPluginList) {
pluginListIter_t it = pPluginList->begin();
pluginListIter_t itEnd = pPluginList->end();
for (; it != itEnd; ++it) {
// For each item in list, run through list again and verify
// that it is not present
pluginListIter_t itTrav = it;
++itTrav;
for (; itTrav != itEnd; ++itTrav)
DEBUGCHK(itTrav != it);
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -