📄 locplugin.cpp
字号:
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Provider <%s> does not have Poll Interval set.\r\n",keyName));
return;
}
m_pollInterval = pRegPlugin->ValueDW(g_rvPollInterval);
m_providerFlags = pRegPlugin->ValueDW(g_rvProviderFlags);
// Load dll and get function exports
if (! LoadPlugin())
return;
m_pfnInitialize = (PFN_PROVINITIALIZE)GetProcAddress(m_dllHInstance,L"ProviderInitialize");
m_pfnGetLocation = (PFN_PROVGETLOCATION)GetProcAddress(m_dllHInstance,L"ProviderGetLocation");
m_pfnStop = (PFN_PROVSTOP)GetProcAddress(m_dllHInstance,L"ProviderStop");
m_pfnUnInitialize = (PFN_PROVUNINITIALIZE)GetProcAddress(m_dllHInstance,L"ProviderUnInitialize");
m_pfnIoctlOpen = (PFN_PROVOPEN)GetProcAddress(m_dllHInstance,L"ProviderIoctlOpen");
m_pfnIoctlCall = (PFN_PROVIOCTL)GetProcAddress(m_dllHInstance,L"ProviderIoctlCall");
m_pfnIoctlClose = (PFN_PROVCLOSE)GetProcAddress(m_dllHInstance,L"ProviderIoctlClose");
if (! (m_pfnInitialize && m_pfnGetLocation && m_pfnStop &&
m_pfnUnInitialize && m_pfnIoctlOpen && m_pfnIoctlCall && m_pfnIoctlClose))
{
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Provider <%s> does not export all required functions\r\n",keyName));
return;
}
PROVIDER_INFORMATION provInfo;
GetProviderInfo(&provInfo);
DWORD err;
provInfo.pluginInfo.pluginState = PLUGIN_STATE_OFF;
if (ERROR_SUCCESS != (err = CallProvInit(&provInfo))) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ProviderInitialize for <%s> returned <0x%08x>. Will not use this provider\r\n",
GetName(),err));
return;
}
// Plugin successfully initialized.
m_pluginState = PLUGIN_STATE_OFF;
m_loadSuccess = TRUE;
#ifdef DEBUG
if (ZONE_PROVIDER) {
DEBUGMSG(1,(L"LOC: Loaded Provider from reg key <%s>. Settings:\r\n",keyName));
DbgPrintSettings();
DEBUGMSG(1,(L"LOC: Poll Interval = <0x%08x>, ProviderFlags = <0x%08x>\r\n",m_pollInterval,m_providerFlags));
}
#endif
}
// Fills out PROVIDER_INFORMATION structure for this provider
void provider_t::GetProviderInfo(PROVIDER_INFORMATION *pProvInfo) {
GetPluginInfo(&pProvInfo->pluginInfo);
pProvInfo->pollInterval = m_pollInterval;
pProvInfo->providerFlags = m_providerFlags;
}
// The provider is entering a new state
void provider_t::SetState(PLUGIN_STATE newState) {
if (m_pluginState == PLUGIN_STATE_ERROR) {
// Once plugin has entered an error condition, it can never get out of it.
return;
}
#ifdef DEBUG
if (m_pluginState != newState) {
DEBUGMSG(ZONE_PROVIDER && ZONE_VERBOSE,(L"LOC: Changing provider <%s> from state <%d> to state <%d>\r\n",
GetName(),m_pluginState,newState));
}
#endif
// For a provider, all report types are set to be in the same state
// and hence there is no need to track state per report (unlike resolvers)
m_pluginState = newState;
}
void provider_t::ReportsUnavailable(void) {
SetState(PLUGIN_STATE_UNAVAILABLE);
// Go back to initial state as to not having received any reports
memset(m_receivedReport,0,sizeof(m_receivedReport));
}
// Called when provider has received a report and is now on.
void provider_t::ReportsAvailable(void) {
SetState(PLUGIN_STATE_ON);
}
// Called when provider is starting up
void provider_t::StartingUp(void) {
SetState(PLUGIN_STATE_STARTING_UP);
}
// Indicates that a fatal error has occured
void provider_t::SetFatalError() {
SetState(PLUGIN_STATE_ERROR);
}
// Indicates that the plugin should generate the requested report type
// Do nothing on providers since once a provider is on it will try to
// generate all report types
void provider_t::RequestReportGeneration(const GUID *pReportType) {
DEBUGCHK(CanGenerateReportType(pReportType));
DEBUGCHK(m_pluginState != PLUGIN_STATE_ERROR);
}
// Like RequestReportGeneration, do nothing for provider case
void provider_t::CancelReportGeneration(const GUID *pReportType) {
DEBUGCHK(CanGenerateReportType(pReportType));
}
// A provider can either generate all of its m_generatedReports or
// none of them. For this reason, just return "global" plugin state
// for this provider. Implement this function in the first place to make
// inheritance easier, since resolvers may have a different per reportType.
PLUGIN_STATE provider_t::GetReportTypeState(const GUID *pReportType) {
return m_pluginState;
}
// Fills PROVIDER_CONTROL_BLOCK that will be sent to the provider
void provider_t::FillPCB(PROVIDER_CONTROL_BLOCK *pPcb, PROVIDER_INFORMATION *pProvInfo) {
GetProviderInfo(pProvInfo);
pPcb->provContext = (HANDLE)this;
pPcb->version = LOCATION_FRAMEWORK_VERSION_CURRENT;
pPcb->pProvInfo = pProvInfo;
pPcb->NewProviderReport = NewProviderReportInd;
pPcb->ProviderUnavailable = ProviderUnavailableInd;
}
// Thread spun up to call the provider's ProviderGetLocation export
void provider_t::GetProviderLocation(void) {
DEBUGMSG(ZONE_PROVIDER| ZONE_THREAD,(L"LOC: Started Provider ProviderGetLocation thread for prov=<%s>\r\n",GetName()));
DEBUGCHK(! g_pLocLock->IsLocked());
g_pLocLock->Lock();
PROVIDER_CONTROL_BLOCK pcb;
PROVIDER_INFORMATION provInfo;
// Plugin better not be on at this stage.
DEBUGCHK(m_pluginState != PLUGIN_STATE_ON);
if (m_pluginState != PLUGIN_STATE_STARTING_UP) {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Will not start provider <%s> because its state was changed before it could be started\r\n",GetName()));
goto done;
}
FillPCB(&pcb,&provInfo);
while (1) {
DEBUGCHK(g_pLocLock->IsLocked());
DEBUGCHK(m_pluginState == PLUGIN_STATE_STARTING_UP);
// Call into the plugin export. Plugin will enter the PLUGIN_STATE_ON
// state the first time it returns a location report.
// This call will block for a very long time - either until
// the ProviderStop() is called or the provider exits abnormally.
if (ERROR_SUCCESS != CallProvGetLocation(&pcb)) {
// Indicates a fatal error. This plugin won't be used anymore.
ReportFatalError();
break;
}
if (m_pluginState != PLUGIN_STATE_SHUTTING_DOWN) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Plugin <%s> returned but was not called from ProviderStop() first. Provider will be disabled\r\n",
GetName()));
ReportFatalError();
break;
}
if (m_immediateRestart) {
// Hit this case when we were in the plugin shutdown process, but
// before we could stop another app requested plugin to start again.
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Was going to shutdown plugin <%s>, but another app requested it so restarting\r\n",GetName()));
m_immediateRestart = FALSE;
SetState(PLUGIN_STATE_STARTING_UP);
continue;
}
break;
}
SetState(PLUGIN_STATE_OFF);
done:
m_workerThrdCookie = 0;
g_pLocLock->Unlock();
DEBUGMSG(ZONE_PROVIDER | ZONE_THREAD,(L"LOC: Ending Provider ProviderGetLocation thread for prov=<%s>\r\n",GetName()));
}
// Schedules a worker to generate provider reports if one is not already running
DWORD provider_t::ScheduleWorkerIfNeeded(void) {
DEBUGCHK(g_pLocLock->IsLocked());
if (m_workerThrdCookie != 0) // worker already running
return ERROR_SUCCESS;
m_workerThrdCookie = g_pThreadPool->ScheduleEvent(::GetProviderLocationThread,this);
if (! m_workerThrdCookie) {
DEBUGMSG_OOM();
return ERROR_OUTOFMEMORY;
}
DEBUGMSG(ZONE_PROVIDER | ZONE_THREAD,(L"LOC: Spinning GetProviderLocation thread for provider <%s>, cookie=<0x%08x>\r\n",
GetName(),m_workerThrdCookie));
return ERROR_SUCCESS;
}
void provider_t::StopPlugin(void) {
DEBUGCHK(g_pLocLock->IsLocked());
DEBUGCHK(m_workerThrdCookie != 0);
// Go back to initial state as to not having received any reports
memset(m_receivedReport,0,sizeof(m_receivedReport));
// The provider Stop() call will return immediately. We transfer
// to the off state once the provider returns.
SetState(PLUGIN_STATE_SHUTTING_DOWN);
CallProvStop();
}
// Calls ProviderInitialize export
DWORD provider_t::CallProvInit(PROVIDER_INFORMATION *pProvInfo) {
DEBUGCHK(g_pLocLock->IsLocked());
DWORD err;
__try {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Calling ProviderInitialize on DLL=<%s>\r\n",GetName()));
// Initialize is only called on LF startup. OK to hold lock.
err = m_pfnInitialize(pProvInfo);
DEBUGMSG(ZONE_PROVIDER,(L"LOC: ProviderInitialize on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
} __except(REPORT_EXCEPTION_TO_WATSON()) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ProviderInitialize caused an exception in DLL=<%s>\r\n",GetName()));
// ReportFatalError(); // Do not call this - plugin constructor will immediately unload it on any error on init.
err = ERROR_INTERNAL_ERROR;
}
return err;
}
// Calls ProviderGetLocation export
DWORD provider_t::CallProvGetLocation(PROVIDER_CONTROL_BLOCK *pProvControlBlock) {
// This call could block a very long time so release lock.
g_pLocLock->Unlock();
DWORD err;
__try {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Calling ProviderGetLocation on DLL=<%s>\r\n",GetName()));
err = m_pfnGetLocation(pProvControlBlock);
DEBUGMSG(ZONE_PROVIDER,(L"LOC: ProviderGetLocation on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
} __except(REPORT_EXCEPTION_TO_WATSON()) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ProviderGetLocation caused an exception. DLL=<%s>\r\n",GetName()));
ReportFatalError();
err = ERROR_INTERNAL_ERROR;
}
g_pLocLock->Lock();
return err;
}
// Calls ProviderStop export. Note that we do NOT release the lock
// when calling into this function, so it must not block
// Generally not a good idea to call 3rd party code with locks held,
// but we can get away with it here because not that many pluggins are
// ever going to be written and they will be done by advanced programmers.
// This no-block requirement is clearly specced.
// Holding the lock enormously simplifies implementation of LF, in particular
// the case where apps try to register for a plugin as it enters shutdown state.
DWORD provider_t::CallProvStop(void) {
DEBUGCHK(g_pLocLock->IsLocked());
DWORD err;
__try {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Calling ProviderStop on DLL=<%s>\r\n",GetName()));
err = m_pfnStop();
DEBUGMSG(ZONE_PROVIDER,(L"LOC: ProviderStop on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
} __except(REPORT_EXCEPTION_TO_WATSON()) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ProviderStop caused an exception. DLL=<%s>\r\n",GetName()));
ReportFatalError();
err = ERROR_INTERNAL_ERROR;
}
return err;
}
// Calls ProviderUnInitialize export
DWORD provider_t::CallProvUnInit(void) {
DEBUGCHK(g_pLocLock->IsLocked());
DWORD err;
__try {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Calling ProviderUninitialize on DLL=<%s>\r\n",GetName()));
// Uninitialize is only called on LF shutdown. OK to hold lock.
err = m_pfnUnInitialize();
DEBUGMSG(ZONE_PROVIDER,(L"LOC: ProviderUninitialize on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
} __except(REPORT_EXCEPTION_TO_WATSON()) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ProviderUninitialize caused an exception. DLL=<%s>\r\n",GetName()));
// ReportFatalError(); - Don't bother at this stage since plugin is going to be unloaded anyway.
err = ERROR_INTERNAL_ERROR;
}
return err;
}
// Calls ProviderIoctlOpen export
DWORD provider_t::CallProvIoctlOpen(void) {
m_numActiveIoctlCallers++;
g_pLocLock->Unlock();
DWORD err;
__try {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Calling ProviderIoctlOpen on DLL=<%s>\r\n",GetName()));
err = m_pfnIoctlOpen();
DEBUGMSG(ZONE_PROVIDER,(L"LOC: ProviderIoctlOpen on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
} __except(REPORT_EXCEPTION_TO_WATSON()) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ProviderIoctlOpen caused an exception. DLL=<%s>\r\n",GetName()));
ReportFatalError();
err = ERROR_INTERNAL_ERROR;
}
g_pLocLock->Lock();
m_numActiveIoctlCallers--;
return err;
}
// Calls ProviderIoctlCall export
DWORD provider_t::CallProvIoctlCall(HANDLE h, DWORD dwCode, BYTE *pBufIn, DWORD cbIn, BYTE *pBufOut, DWORD *pcbOut) {
m_numActiveIoctlCallers++;
g_pLocLock->Unlock();
DWORD err;
__try {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Calling ProviderIoctlCall on DLL=<%s>\r\n",GetName()));
err = m_pfnIoctlCall(h, dwCode, pBufIn, cbIn, pBufOut, pcbOut);
DEBUGMSG(ZONE_PROVIDER,(L"LOC: ProviderIoctlCall on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
} __except(REPORT_EXCEPTION_TO_WATSON()) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ProviderIoctlCall caused an exception. DLL=<%s>\r\n",GetName()));
ReportFatalError();
err = ERROR_INTERNAL_ERROR;
}
g_pLocLock->Lock();
m_numActiveIoctlCallers--;
return err;
}
// Calls ProviderIoctlClose export
DWORD provider_t::CallProvIoctlClose(HANDLE h) {
m_numActiveIoctlCallers++;
g_pLocLock->Unlock();
DWORD err;
__try {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Calling ProviderClose on DLL=<%s>\r\n",GetName()));
err = m_pfnIoctlClose(h);
DEBUGMSG(ZONE_PROVIDER,(L"LOC: ProviderClose on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
} __except(REPORT_EXCEPTION_TO_WATSON()) {
DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ProviderClose caused an exception. DLL=<%s>\r\n",GetName()));
ReportFatalError();
err = ERROR_INTERNAL_ERROR;
}
g_pLocLock->Lock();
m_numActiveIoctlCallers--;
return err;
}
//
// resolver_t implements resolver wrapper
//
resolver_t::~resolver_t() {
if (! m_loadSuccess) {
DEBUGCHK(g_serviceState == SERVICE_STATE_STARTING_UP);
// If loading the plugin failed, then we shouldn't call into
// Stop/Uninitialize at all.
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -