⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 locplugin.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
done:
    for (DWORD i = 0; i < m_numGeneratedReportTypes; i++) {
        // Resolver stop may have been called on another thread.  This takes them
        // to state PLUGIN_STATE_SHUTTING_DOWN, it's this thread's responsibility
        // to turn them off.

        // If yet another thread registered for a report type this resolver
        // generates after Resolver.Stop() but before we got here, then 
        // it will have its state set as PLUGIN_STATE_STARTING_UP and it will be
        // available for scheduling just as it should be.
        if (m_reportStates[i] == PLUGIN_STATE_SHUTTING_DOWN)
            SetState(&m_generatedReportTypes[i],PLUGIN_STATE_OFF);
    }

    // Reset this regardless of previous value.
    m_immediateRestart = FALSE;

    DEBUGMSG(ZONE_RESOLVER | ZONE_THREAD,(L"LOC: Ending ResolverGetLocation thread for resolver <%s>\r\n",GetName()));
    g_pLocLock->Unlock();
}

// A provider that generates a report that the resolver can resolve
// indicates it (via the report collector) by calling this function.
// Possibly save new provider report and possibly spin worker thread
void resolver_t::NewReportFromProvider(provider_t *pProv, reportCol_t *pRC) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(pProv->GetState() == PLUGIN_STATE_ON);

    if (m_pluginState <= PLUGIN_STATE_SHUTTING_DOWN) {
        // Resolvers are always given indications of new reports, even when
        // they're not active.  Check that we care about report here.
        return;
    }

    // Do checks to make sure that the provider generating this report is one
    // that we care about.  Consider for instance a system with Providers P1
    // and P2, P1 higher priority, both capable of generating reports for this
    // resolver.  If P1 has given us a report already, when P2 calls this function
    // we want to IGNORE P2's report since P1 was higher priority.

    // Relying on the reports collector's priority filtering to do this work
    // for the resolver will not work in all cases, so do it again here.

    if (m_providerGenerator == NULL) {
        // No provider registered yet, so use this provider
        ;
    }
    else if (m_providerGenerator->GetState() != PLUGIN_STATE_ON) {
        // We have another (possibly higher priority) plugin associated
        // with this RC already, however that plugin is not active.
        // In this case, take what we can get and use the plugin that is 
        // currently generating data for us.
        DEBUGCHK(m_providersAvailable);
    }
    else if (m_providerGenerator->GetStartOrder() < pProv->GetStartOrder())
    {
        // We have another plugin generating reports and it is of higher
        // priority, so ignore any reports this plugin happens to generate.
        DEBUGMSG(ZONE_PLUGIN,(L"LOC: Resolver <%s> ignores provider <%s> report since a higher prio plugin generates a supported type for this resolver\r\n",
                 GetName(),pProv->GetName()));
        DEBUGCHK(m_providersAvailable);
        return;
    }

    // There must be a provider available for us to have got this reports.
    m_providersAvailable = TRUE;

    m_providerGenerator = pProv;
    m_reportCollector   = pRC;

    // Store the report the provider generated
    DEBUGMSG(ZONE_PLUGIN,(L"LOC: Provider <%s> has given resolver <%s> a new report to resolve\r\n",
             pProv->GetName(),GetName()));

    if (m_workerThrdCookie == 0) {
        // m_workerThrdCookie != 0 means thread has already been scheduled.
        // Only schedule one thread per resolver.
        ScheduleNextResolution();
    }
}

// When there are no providers that generate any reports this resolver
// can support, then record this and take resolver to an unavailable state.
void resolver_t::NoProvidersAvailable(void) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(m_providersAvailable);

    DEBUGMSG(ZONE_RESOLVER,(L"LOC: Resolver <%s> does not have any providers available currently.  Moving to unavailable state\r\n",
             GetName()));

    m_providersAvailable = FALSE;

    // Mark any report type that is starting up or ON as unavailable.
    for (DWORD i = 0; i < m_numSupportedReportTypes; i++) {
        if (m_reportStates[i] > PLUGIN_STATE_UNAVAILABLE)
            SetState(&m_generatedReportTypes[i],PLUGIN_STATE_UNAVAILABLE);
    }

    // Unschedule the worker thread, if there is one and if we can.
    // This will NOT terminate a running ResolverGetLocation thread, but if 
    // one was scheduled to run in the future it will make sure we don't bother
    // doing this work.
    if (m_workerThrdCookie && g_pThreadPool->UnScheduleEvent(m_workerThrdCookie)) {
        DEBUGMSG(ZONE_RESOLVER | ZONE_THREAD, (L"LOC: Unscheduled ResolverGetLocation worker cookie <%d> because of no available provs\r\n",
                 m_workerThrdCookie));
        m_workerThrdCookie = 0;
    }
}

// Determine how far into the future the next call to GetResolverLocation worker
// thread should be.  This is based on the last time the resolver was called,
// whether the call was successful (at least one report resolved) or not, 
// and the resolver's registry config for requery timeouts.
DWORD resolver_t::DetermineDelayUntilNextResolution(void) {
    DWORD timeout;

    if (GetState() == PLUGIN_STATE_UNAVAILABLE) {
        // Last attempt to query plugin failed
        timeout = m_retryOnFailure;
    }
    else {
        // Last attempt to query plugin was successful (for at least one report)
        // or this is the first time we're starting up the plugin after it 
        // has been stopped for a while.
        timeout = m_minRequery;
    }

    __int64 currentTime;
    GetCurrentFT((FILETIME*)&currentTime);

    __int64 resDeltaFT = currentTime - m_lastResolution;

    if ((resDeltaFT < 0) || ((resDeltaFT / SVS_FILETIME_TO_MILLISECONDS) > MAXDWORD)) {
        // The system clock has moved backwards or way into future since 
        // the last resolution.  In this case just 
        // schedule the next resolution to be immediate.
        return 0;
    }

    // Number of milliseconds since last resolution.
    DWORD resDeltaMS = (resDeltaFT / SVS_FILETIME_TO_MILLISECONDS);
    
    if (resDeltaMS < timeout) {
        // The next time we should be scheduled is in the future
        return (timeout - resDeltaMS);
    }

    // Otherwise we should schedule the resolution to run immediately.
    return 0;
}

// Schedule the next thread to call ResolverGetLocation on this resolver.
void resolver_t::ScheduleNextResolution(void) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(m_workerThrdCookie == 0);

    DWORD delay;

    if (m_getRepThrdCalledFirstTime == TRUE) {
        delay = DetermineDelayUntilNextResolution();
    }
    else {
        // This is the first time ResolverGetLocation is to be scheduled.
        // Schedule it immediately.
        delay = 0;
    }

    DEBUGMSG(ZONE_RESOLVER,(L"LOC: Scheduling resolver thread for <%s> to run <%d> ms from now\r\n",
                              GetName(),delay));

    m_workerThrdCookie = g_pThreadPool->ScheduleEvent(GetResolverLocationThread,this,delay);

#ifdef DEBUG
    if (m_workerThrdCookie == 0) {
        DEBUGMSG_OOM(); 
    }
    else {
        DEBUGMSG(ZONE_RESOLVER | ZONE_THREAD,(L"LOC: Spinning GetResolverLocation thread for resolver <%s>, cookie=<0x%08x>\r\n",
                 GetName(),m_workerThrdCookie));
    }
#endif
}

// Thread spun to call resolver's ResolverStop export.  We have to
// check to make sure resolver hasn't been restarted in the interim.
void resolver_t::StopPlugin(void) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(m_immediateRestart == FALSE);

    // UnScheduleEvent only returns TRUE if the scheduled worker thread
    // was not running.  So try to unschedule the worker if possible.
    if (m_workerThrdCookie && g_pThreadPool->UnScheduleEvent(m_workerThrdCookie)) {
        DEBUGMSG(ZONE_RESOLVER | ZONE_THREAD,(L"LOC: Unscheduled GetResolverLocation thread for <%s>, cookie=<0x%08x>\r\n",
                 GetName(),m_workerThrdCookie));
        m_workerThrdCookie = 0;
    }

    // Reset this, regardless of whether provider(s) is available or not, because
    // the other place we reset this (NewReportFromProvider) will not be called
    // now that resolver has been stopped.  If no providers are available
    // the next time resolver is attempted to be started, then the startup
    // logic will do the right thing and not try to restart this resolver.
    m_providersAvailable = TRUE;

    if (m_getRepThrdCalledFirstTime == FALSE) {
        // Possible in case where the stop was called before the worker
        // thread got started.  Since resolver's GetResolverLocation was never
        // called, don't bother calling its stop routine.

        // This could happen if a resolver requested a provider to generate
        // reports for it, but the resolver was asked to stop before the provider 
        // generated a report.

        // Transition straight to OFF - no more work required here
        SetAllReportStates(PLUGIN_STATE_OFF);
        return;
    }

    if (m_workerThrdCookie == 0) {
        // If the worker thread isn't running, then we can immediately transition
        // to the off-state.
        SetAllReportStates(PLUGIN_STATE_OFF);
    }
    else {
        // If the worker thread is running, then we can't immediately indicate
        // the report states as off.  We need instead to to mark them as 
        // shutting down and leave it to worker to set them as off once it has
        // returned from its call to ResolverGetLocation.

        for (DWORD i = 0; i < m_numGeneratedReportTypes; i++) {
            // Update state only if it was previously on (don't take
            // a state from Off->ShuttingDown for instance)
            if (m_reportStates[i] >= PLUGIN_STATE_UNAVAILABLE)
                m_reportStates[i] = PLUGIN_STATE_SHUTTING_DOWN;
        }
        m_pluginState = PLUGIN_STATE_SHUTTING_DOWN;
    }

    CallResStop();
    m_getRepThrdCalledFirstTime = FALSE;

    DEBUGMSG(ZONE_RESOLVER | ZONE_THREAD,(L"LOC: Completed ResolverStop thread for resolver <%s>\r\n",GetName()));
}

// Calls ResolverInitialize export
DWORD resolver_t::CallResInit(RESOLVER_INFORMATION *pResInfo) {
    DEBUGCHK(g_pLocLock->IsLocked());

    DWORD err;
    __try {
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Calling ResolverInitialize on DLL=<%s>\r\n",GetName()));
        // Initialize is only called on LF startup.  OK to hold lock.
        err = m_pfnInitialize(pResInfo);
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: ResolverInitialize on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
    } __except(REPORT_EXCEPTION_TO_WATSON()) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ResolverInitialize 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 ResolverGetLocation export 
DWORD resolver_t::CallResGetLocation(RESOLVER_CONTROL_BLOCK *pResControlBlock) {
    g_pLocLock->Unlock();

    DWORD err;
    __try {
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Calling ResolverGetLocation on DLL=<%s>\r\n",GetName()));
        err = m_pfnGetLocation(pResControlBlock);
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: ResolverGetLocation on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
    } __except(REPORT_EXCEPTION_TO_WATSON()) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ResolverGetLocation caused an exception in DLL=<%s>\r\n",GetName()));
        ReportFatalError();
        err = ERROR_INTERNAL_ERROR;
    }

    g_pLocLock->Lock();
    return err;
}

// Calls ResolverStop export.  See CallProvStop() comments for more info.
DWORD resolver_t::CallResStop(void) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(m_getRepThrdCalledFirstTime == TRUE);

    DWORD err;
    __try {
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Calling ResolverStop on DLL=<%s>\r\n",GetName()));
        err = m_pfnStop();
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: ResolverStop on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
    } __except(REPORT_EXCEPTION_TO_WATSON()) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ResolverStop caused an exception in DLL=<%s>\r\n",GetName()));
        ReportFatalError();
        err = ERROR_INTERNAL_ERROR;
    }

    return err;
}

// Calls ResolverUnInitialize export
DWORD resolver_t::CallResUnInit(void) {
    DEBUGCHK(g_pLocLock->IsLocked());

    DWORD err;
    __try {
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Calling ResolverUnInitialize on DLL=<%s>\r\n",GetName()));
        // Uninit is only called on LF shutdown.  OK to hold lock.
        err = m_pfnUnInitialize();
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: ResolverUnInitialize on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
    } __except(REPORT_EXCEPTION_TO_WATSON()) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ResolverUnInitialize caused an exception in DLL=<%s>\r\n",GetName()));
        err = ERROR_INTERNAL_ERROR;
        // ReportFatalError(); - since the plugin is being unloaded anyway, don't bother
    }
    
    return err;
}

// Calls ResolverIoctlOpen export
DWORD resolver_t::CallResIoctlOpen(void) {
    m_numActiveIoctlCallers++;
    g_pLocLock->Unlock();
    
    DWORD err;
    __try {
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Calling ResolverIoctlOpen on DLL=<%s>\r\n",GetName()));
        err = m_pfnIoctlOpen();
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: ResolverIoctlOpen on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
    } __except(REPORT_EXCEPTION_TO_WATSON()) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ResolverIoctlOpen caused an exception in DLL=<%s>\r\n",GetName()));
        ReportFatalError();
        err = ERROR_INTERNAL_ERROR;
    }

    g_pLocLock->Lock();
    m_numActiveIoctlCallers--;
    return err;
}

// Calls ResolverIoctlCall export
DWORD resolver_t::CallResIoctlCall(HANDLE h, DWORD dwCode, BYTE *pBufIn, DWORD cbIn, BYTE *pBufOut, DWORD *pcbOut) {
    m_numActiveIoctlCallers++;
    g_pLocLock->Unlock();

    DWORD err;
    __try {
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Calling ResolverIoctlCall on DLL=<%s>\r\n",GetName()));
        err = m_pfnIoctlCall(h, dwCode, pBufIn, cbIn, pBufOut, pcbOut);
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: ResolverIoctlCall on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
    } __except(REPORT_EXCEPTION_TO_WATSON()) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ResolverIoctlCall caused an exception in DLL=<%s>\r\n",GetName()));
        ReportFatalError();
        err = ERROR_INTERNAL_ERROR;
    }

    g_pLocLock->Lock();
    m_numActiveIoctlCallers--;
    return err;
}

// Calls ResolverIoctlClose export
DWORD resolver_t::CallResIoctlClose(HANDLE h) {
    m_numActiveIoctlCallers++;
    g_pLocLock->Unlock();

    DWORD err;
    __try {
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Calling ResolverIoctlClose on DLL=<%s>\r\n",GetName()));
        err = m_pfnIoctlClose(h);
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: ResolverIoctlClose on DLL=<%s> returned <0x%08x>\r\n",GetName(),err));
    } __except(REPORT_EXCEPTION_TO_WATSON()) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ResolverIoctlClose caused an exception in DLL=<%s>\r\n",GetName()));
        ReportFatalError();
        err = ERROR_INTERNAL_ERROR;
    }

    g_pLocLock->Lock();
    m_numActiveIoctlCallers--;
    return err;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -