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

📄 locplugin.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        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 + -