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

📄 locplugin.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    DEBUGMSG(ZONE_INIT | ZONE_RESOLVER,(L"LOC: Beginning to uninit Resolver DLL <%s>\r\n",GetName()));

    if (m_pluginState >= PLUGIN_STATE_UNAVAILABLE) {
        // The plugin's stop still needs to be called.
        if (m_getRepThrdCalledFirstTime) {
            m_pluginState = PLUGIN_STATE_SHUTTING_DOWN;
            CallResStop();
        }
    }

    // Wait until any outstanding references to the resolver have stopped
    WaitOnOpenIoctlCalls();
    WaitOnRunningGetLocThread();

    // Finally, call the uninit.
    CallResUnInit();

    DEBUGMSG(ZONE_INIT | ZONE_RESOLVER,(L"LOC: Completed uninit Resolver DLL <%s>\r\n",GetName()));
}

// Called on initialization of resolver - reads in base settings & calls 
// ResolverInitialize
void resolver_t::InitResolver(CReg *pRegPlugin, const WCHAR *keyName) {
    DEBUGMSG(ZONE_RESOLVER,(L"LOC: Initializing resolver <%s>\r\n",keyName));
    DEBUGCHK(m_pluginState == PLUGIN_STATE_ERROR); // Should've been reset before calling here

    DWORD regValueType;
    DWORD regValueLen;

    m_lastResolution = 0; 
    m_getRepThrdCalledFirstTime = FALSE;

    SetAllReportStates(PLUGIN_STATE_OFF); 
    m_pluginState = PLUGIN_STATE_ERROR;

    // Only indicate no providers when we actually have providers indicating failure.
    // By default assume providers can in theory work, only set this FALSE when
    // all providers we would care about actually fail on us.
    m_providersAvailable = TRUE;

    m_providerGenerator = NULL;
    m_reportCollector   = NULL;

    // Fill out remainder of array with report types not generated
    for (DWORD i = m_numGeneratedReportTypes; i < MAX_PLUGIN_REPORT_TYPES; i++)
        m_reportStates[i] = PLUGIN_STATE_NOT_SUPPORTED;

    // Read registry settings
    if (! pRegPlugin->GetLengthAndType(g_rvMinimumRequery, &regValueLen, &regValueType)) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Resolver <%s> does not have MinimumRequery set.\r\n",keyName));
        return;
    }
    m_minRequery = pRegPlugin->ValueDW(g_rvMinimumRequery);

    m_resolverFlags = pRegPlugin->ValueDW(g_rvResolverFlags);

    m_numSupportedReportTypes = 0;
    if (! ReadGuidsFromReg(pRegPlugin,keyName,g_rvSupportedReports,m_supportedReportTypes,
                           &m_numSupportedReportTypes,MAX_PLUGIN_REPORT_TYPES)) {
        return;
    }

    // Load dll and get function exports
    if (! LoadPlugin())
        return;

    m_pfnInitialize   = (PFN_RESINITIALIZE)GetProcAddress(m_dllHInstance,L"ResolverInitialize");
    m_pfnGetLocation  = (PFN_RESGETLOCATION)GetProcAddress(m_dllHInstance,L"ResolverGetLocation");
    m_pfnStop         = (PFN_RESSTOP)GetProcAddress(m_dllHInstance,L"ResolverStop");
    m_pfnUnInitialize = (PFN_RESUNINITIALIZE)GetProcAddress(m_dllHInstance,L"ResolverUnInitialize");
    m_pfnIoctlOpen    = (PFN_RESOPEN)GetProcAddress(m_dllHInstance,L"ResolverIoctlOpen");
    m_pfnIoctlCall    = (PFN_RESIOCTL)GetProcAddress(m_dllHInstance,L"ResolverIoctlCall");
    m_pfnIoctlClose   = (PFN_RESCLOSE)GetProcAddress(m_dllHInstance,L"ResolverIoctlClose");

    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;
    }

    RESOLVER_INFORMATION resInfo;
    GetResolverInfo(&resInfo);
    DWORD err;

    resInfo.pluginInfo.pluginState = PLUGIN_STATE_OFF;

    if (ERROR_SUCCESS != (err = CallResInit(&resInfo))) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: ResolverInitialize for <%s> returned <0x%08x>.  Will not use this provider\r\n",
                              GetName(),err));
        return;
    }

    m_pluginState = PLUGIN_STATE_OFF;
    m_loadSuccess = TRUE;

#ifdef DEBUG
    if (ZONE_RESOLVER) {
        DEBUGMSG(1,(L"LOC: Loaded Resolver from reg key <%s>.  Settings:\r\n",keyName));
        DbgPrintSettings();
        DEBUGMSG(1,(L"LOC:   MinRequery = <0x%08x>, ResolverFlags = <0x%08x>\r\n",m_minRequery,m_resolverFlags));
        DEBUGMSG(1,(L"LOC:   Supported Guids\r\n"));
        DbgPrintGuids(m_supportedReportTypes,m_numSupportedReportTypes);
    }
#endif

    return;
}

// Fills out RESOLVER_INFORMATION structure for this resolver
void resolver_t::GetResolverInfo(RESOLVER_INFORMATION *pResInfo) {
    GetPluginInfo(&pResInfo->pluginInfo);
    pResInfo->minRequeryInterval  = m_minRequery;
    pResInfo->numReportsSupported = m_numSupportedReportTypes;
    memcpy(&pResInfo->reportsSupported,m_supportedReportTypes,sizeof(m_supportedReportTypes));
    pResInfo->resolverFlags       = m_resolverFlags;
}

// Returns which reportTypes the plugin can possibly generate
void resolver_t::GetSupportedReportInfo(GUID *pReportTypes, DWORD *numReportTypes) {
    if ((m_numSupportedReportTypes == 0) || (m_numSupportedReportTypes > MAX_PLUGIN_REPORT_TYPES)) {
        // pReportTypes is guaranteed to be MAX_PLUGIN_REPORT_TYPES*sizeof(GUID)
        // We do run-time check, rather only having DEBUGCHK, to satisfy prefix.
        DEBUGCHK(0);
        *numReportTypes = 0;
        return;
    }

    *numReportTypes = m_numSupportedReportTypes;
    memcpy(pReportTypes,m_supportedReportTypes,m_numSupportedReportTypes*sizeof(GUID));
}

// Returns TRUE if the resolver can (in theory) support reports of a particular
// report type for resolution.
BOOL resolver_t::CanSupportReportType(const GUID *pReportType) {
    for (DWORD i = 0; i < m_numSupportedReportTypes; i++) {
        if (0 == memcmp(&m_supportedReportTypes[i],pReportType,sizeof(GUID)))
            return TRUE;
    }
    return FALSE;
}

// For resolvers, since each report type may or may not be available independent
// of the other report types *for the same resolver DLL*, need a little more
// complicated logic here.  (Note that provider implementation of this function
// just returns the global state for that provider)
PLUGIN_STATE resolver_t::GetReportTypeState(const GUID *pReportType) {
    for (DWORD i = 0; i < m_numGeneratedReportTypes; i++) {
        if (0 == memcmp(pReportType,&m_generatedReportTypes[i],sizeof(GUID)))
            return m_reportStates[i];
    }

    // Indicates plugin does not support this type.
    return PLUGIN_STATE_NOT_SUPPORTED;
}

// Indicates particular report type isn't available anymore
void resolver_t::ReportTypeUnavailable(const GUID *pReportType) {
    SetState(pReportType,PLUGIN_STATE_UNAVAILABLE);
}

void resolver_t::ReportTypeAvailable(const GUID *pReportType) {
    SetState(pReportType,PLUGIN_STATE_ON);
}

// Indicates that the Resolver should generate the requested report type
void resolver_t::RequestReportGeneration(const GUID *pReportType) {
    DEBUGCHK(m_pluginState != PLUGIN_STATE_ERROR);

    DWORD index = FindGeneratedReportIndex(pReportType);
    DEBUGCHK(index != (DWORD)-1);

    if (m_reportStates[index] == PLUGIN_STATE_OFF) {
        // Only update the state if we're transitioning from the OFF state.
        // If we're in another state (say already ON or Unavail) then leave it as it previously was.
        SetState(pReportType,PLUGIN_STATE_STARTING_UP);
    }
}

void resolver_t::CancelReportGeneration(const GUID *pReportType) {
    DEBUGCHK(CanGenerateReportType(pReportType));
    DEBUGCHK(m_pluginState >= PLUGIN_STATE_UNAVAILABLE);

    // Set individual report state to shutting down for now.  resolver_t::StopPlugin
    // and/or GetResolverLocation will ultimately set this state to OFF.
    SetState(pReportType,PLUGIN_STATE_SHUTTING_DOWN);
}


// Change the state of particular reportType in resolver.  Note that report
// types in the same resolver may be independent of each other; i.e. generated
// report type #1 may be PLUGIN_STATE_ON while #2 report is PLUGIN_STATE_OFF/UNAVAIL/...
void resolver_t::SetState(const GUID *pReportType, PLUGIN_STATE newState) {
    if (m_pluginState == PLUGIN_STATE_ERROR) {
        // Once plugin has entered an error condition, it can never get out of it.
        return;
    }

    DWORD index = FindGeneratedReportIndex(pReportType);
    // Plugin Manager will only call this function if resolver supports it.
    DEBUGCHK(index < m_numGeneratedReportTypes);

#ifdef DEBUG
    if (newState != m_reportStates[index]) {
        DEBUGMSG(ZONE_RESOLVER && ZONE_VERBOSE,(L"LOC: Changing plugin <%s>, for Report type <" SVSUTIL_GUID_FORMAT_W 
                                                L"> from state <%d> to state <%d>\r\n",
                 GetName(),SVSUTIL_PGUID_ELEMENTS(pReportType),
                 m_pluginState,newState));
    }
#endif

    m_reportStates[index] = newState;

    // What we change the "global" resolver state to (i.e. what we tell 
    // apps querying this plugin state) is based on the "highest" available
    // report.  The PLUGIN_STATE enum is ordered with the highest 
    // (PLUGIN_STATE_ON) coming last.
    m_pluginState = PLUGIN_STATE_ERROR;

    for (DWORD i = 0; i < m_numGeneratedReportTypes; i++)
        m_pluginState = max(m_pluginState,m_reportStates[i]);
}

// Helper to change all report states at the same type
void resolver_t::SetAllReportStates(PLUGIN_STATE newState) {
    for (DWORD i = 0; i < m_numGeneratedReportTypes; i++)
        m_reportStates[i] = newState;

    m_pluginState = newState;
}

// Indicates that a fatal error has occured 
void resolver_t::SetFatalError() {
    SetAllReportStates(PLUGIN_STATE_ERROR);
}

// Function that sets up resolver control block to be sent to the resolver
void resolver_t::FillRCB(RESOLVER_CONTROL_BLOCK *pRcb, RESOLVER_INFORMATION *pResInfo, reportSmartPtr_t &pProvReport) {
    pRcb->numTypesToResolve   = 0;

    // Determine which report types the resolver should be asked to return.
    for (DWORD i = 0; i < m_numGeneratedReportTypes; i++) {
        PLUGIN_STATE repState = m_reportStates[i];

        if ((repState == PLUGIN_STATE_ON) || (repState == PLUGIN_STATE_STARTING_UP) ||
            (repState == PLUGIN_STATE_UNAVAILABLE))
        {
            // In this case we try to resolve this report
            memcpy(&pRcb->typesToResolve[pRcb->numTypesToResolve],&m_generatedReportTypes[i],sizeof(GUID));
            pRcb->numTypesToResolve++;
        }
    }

    if (pRcb->numTypesToResolve == 0) {
        // No work to do in this case; caller will return immediately
        return;
    }

    GetResolverInfo(pResInfo);

    pRcb->version           = LOCATION_FRAMEWORK_VERSION_CURRENT;
    pRcb->resContext        = (HANDLE)this;
    pRcb->pResInfo          = pResInfo;

    pProvReport             = m_reportCollector->GetReport();
    pRcb->provReport        = pProvReport;

    pRcb->NewResolverReport = NewResolverReportInd;
}

// Calls into the resolver's ResolverGetLocation to resolve reports.
void resolver_t::GetResolverLocation(void) {
    RESOLVER_CONTROL_BLOCK rcb;
    RESOLVER_INFORMATION   resInfo;
    DWORD                  i;
    FILETIME               reportCreationTime;

    g_pLocLock->Lock();

    DEBUGCHK(m_workerThrdCookie != 0); 

    // Hold a smart pointer reference to the memory returned by the RC.
    // Do this so that should the RC receive a new report during processing
    // of this function, the memory won't be freed because we'll have an 
    // extra ref count.
    reportSmartPtr_t pProvReport = NULL;

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

    if (m_pluginState <= PLUGIN_STATE_SHUTTING_DOWN) {
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Exiting thread for ResolveLookup for <%s> since state = <%d>\r\n",
                                GetName(),m_pluginState));
        m_workerThrdCookie = 0;
        goto done;
    }

    if (m_providersAvailable == FALSE) {
        // There is a small time window where the last provider could've become unavailable
        // before this worker thread could be unscheduled.  Since we ignore 
        // new resolver reports once we reach this stage anyway, don't even
        // bother calling resolver DLL export.
        DEBUGMSG(ZONE_RESOLVER,(L"LOC: Exiting thread for ResolveLookup for <%s> since no providers are available\r\n",GetName()));
        m_workerThrdCookie = 0;
        goto done;
    }

    // Fill out data structures to pass to LF.
    FillRCB(&rcb,&resInfo,pProvReport);
    memcpy(&reportCreationTime,&((LOCATION_REPORT_BASE*)rcb.provReport)->creationTime,sizeof(reportCreationTime));
    // Reset our received reports for the next pass
    memset(m_receivedReport,0,sizeof(m_receivedReport));


    // If we don't need any report types resolved, then stop now.
    if (rcb.numTypesToResolve == 0) {
        DEBUGMSG(ZONE_RESOLVER,(L"LOCATION: GetResolverLocation thread for <%s> returning since no reports needed to resolve\r\n",GetName()));
        m_workerThrdCookie = 0;
        goto done;
    }

#ifdef DEBUG
    if (ZONE_RESOLVER) {
        DEBUGMSG(1,(L"LOC: About to call ResolverGetLocation for Resolver <%s> with following report type(s) to resolve\r\n",GetName()));
        DbgPrintGuids(rcb.typesToResolve,rcb.numTypesToResolve);
    }
#endif

    // Indicate that this thread has now been called.
    m_getRepThrdCalledFirstTime = TRUE;

    // Actually call the DLL export.  This may block for a long time potentially,
    // but it is not designed to block as long as there are apps registered
    // for it (unlike ProviderGetLocation()).
    DWORD err = CallResGetLocation(&rcb);
    if (err != ERROR_SUCCESS) {
        ReportFatalError();
        m_workerThrdCookie = 0;
        goto done;
    }

    // During the resolution cycle, the LF service itself has 
    // been shutdown.  No point in continuing.
    if (g_serviceState != SERVICE_STATE_ON) {
        m_workerThrdCookie = 0;
        goto done;
    }

    // Now that call has returned, for any registered report type for 
    // which a report was not returned, mark as unavailable and have
    // plugin manager start the next in line.
    for (i = 0; i < m_numGeneratedReportTypes; i++) {
        if ((m_reportStates[i] >= PLUGIN_STATE_STARTING_UP) && !m_receivedReport[i]) {
            // We wanted a report for this type but resolver did not generate one.
            // The first time this occurs, alert plugin manager.
            g_pPluginMgr->ResolverReportTypeUnavailable(this, &m_generatedReportTypes[i]);
            DEBUGCHK(m_reportStates[i] == PLUGIN_STATE_UNAVAILABLE);
        }
    }

    m_workerThrdCookie = 0;
    GetCurrentFT((FILETIME*)&m_lastResolution);

    if (m_providersAvailable == FALSE) {
        // During ResolverGetLocationCall(), all possible providers that could
        // generate reports for this resolver have become unavailable.
        // Do not reschedule another worker thread - wait for provider 
        // to become available again.
        goto done;
    }

    if (m_pluginState == PLUGIN_STATE_UNAVAILABLE) {
        // If we failed to resolve any reports in our last resolution
        // attempt, then we need to try again. 
        ScheduleNextResolution();
    }
    else if ((m_pluginState >= PLUGIN_STATE_STARTING_UP) && (m_reportCollector->HasNewReport(&reportCreationTime))) {
        // A new provider report has arrived since we have completed this resolution.
        // Schedule a new worker thread to do the lookup
        ScheduleNextResolution();
    }
    else {
        ;
        // else {...} we have resolved a report & no new provider reports have 
        // since arrived, so no need to reschedule.  This worker will be rescheduled
        // when the next provider report comes in.
    }

⌨️ 快捷键说明

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