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

📄 loccore.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//

// Abstract: Location framework core logic

#include <locCore.hpp>


//
//  Location framework debug info
//

#if defined(UNDER_CE) && defined (DEBUG)
  DBGPARAM dpCurSettings = {
    TEXT("LFSVC"), {
    TEXT("Init"),TEXT("Service"),TEXT("Provider"),TEXT("Resolver"),
    TEXT("Report Collector"),TEXT("Plugin Mgr"),TEXT("API"),TEXT("Thread"),
    TEXT(""),TEXT(""),TEXT(""),TEXT("Verbose"),
    TEXT("Alloc"),TEXT("Function"),TEXT("Error"),TEXT("Warn") },
    0xC000
  }; 
#endif

// 
//  Define registry key and value constants
//

const WCHAR *g_rkLocBase   = L"System\\CurrentControlSet\\Location Framework";
const WCHAR *g_rkProviders = L"Providers";
const WCHAR *g_rkResolvers = L"Resolvers";

const WCHAR *g_rvDll                     = L"DLL";
const WCHAR *g_rvFriendlyName            = L"FriendlyName";
const WCHAR *g_rvGuid                    = L"GUID";
const WCHAR *g_rvPreference              = L"Preference";
const WCHAR *g_rvPluginFlags             = L"PluginFlags";
const WCHAR *g_rvVersion                 = L"Version";
const WCHAR *g_rvProviderFlags           = L"ProviderFlags";
const WCHAR *g_rvResolverFlags           = L"ResolverFlags";
const WCHAR *g_rvPollInterval            = L"PollInterval";
const WCHAR *g_rvRetryOnFailure          = L"RetryOnFailure";
const WCHAR *g_rvMaximumInitialWait      = L"MaximumInitialWait";
const WCHAR *g_rvGeneratedReports        = L"GeneratedReports";
const WCHAR *g_rvSupportedReports        = L"SupportedReports";
const WCHAR *g_rvMinimumRequery          = L"MinimumRequery";

//
//  Global variables
//

// Global lock
SVSSynch *g_pLocLock;
// Thread pool 
SVSThreadPool *g_pThreadPool;
// Current service state of location framework (from service.h)
DWORD g_serviceState;
// Maps handles between application layer and this service
handleMgr_t *g_pHandleMgr;

// Wait this many milliseconds on each poll to see if we can unload LF.
const DWORD g_pollOnUnload = 100;
// When trying to unload, if we have to go into a wait loop > 50 times, DEBUGCHK
const DWORD g_pollRetriesWarnOnUnload = 50;
// Maximum number of simultaneous worker threads for location framework.
static const DWORD g_maxWorkerThreads = 40;

//
//  Startup and shutdown related functionality
//

// Initializes service.  Only called once from DllMain().  All functions
// called here MUST be DllMain safe.
BOOL InitLocService(void) {
    // Init global critical section, other truly global stuff...
    svsutil_Initialize();
 
    g_pLocLock = new SVSSynch();
    if (g_pLocLock == NULL) {
        DEBUGMSG_OOM();
        return FALSE;
    }

    g_pHandleMgr = new handleMgr_t();
    if ((g_pHandleMgr == NULL) || (!g_pHandleMgr->IsHandleMgrInited())) {
        DEBUGMSG_OOM();
        return FALSE;
    }

    g_pThreadPool = new SVSThreadPool(g_maxWorkerThreads);
    if (g_pThreadPool == NULL) {
        DEBUGMSG_OOM();
        delete g_pLocLock;
        return FALSE;
    }

    g_serviceState = SERVICE_STATE_UNINITIALIZED;
    return TRUE;
}

// DeInitializes service.  Only called once from DllMain().  Make sure
// everything is DllMain safe.
void DeInitLocService(void) {
    DEBUGCHK(g_serviceState == SERVICE_STATE_UNLOADING);

#ifdef SVSUTIL_DEBUG_THREADS
	// DEBUG verify that that threadpool has no running threads.  
    // This function is called from DllMain() where we must not block 
	SVS_THREAD_POOL_STATS threadPoolStats;
	g_pThreadPool->GetStatistics(&threadPoolStats);
	DEBUGCHK(threadPoolStats.cThreadsRunning == 0);
#endif

    if (g_pThreadPool) {
        delete g_pThreadPool;
        g_pThreadPool = NULL;
    }

    if (g_pHandleMgr) {
        delete g_pHandleMgr;
        g_pHandleMgr = NULL;
    }

    if (g_pLocLock) {
        delete g_pLocLock;
        g_pLocLock = NULL;
    }

    svsutil_DeInitialize();
}

// Frees globals that are created/destroyed when service is stopped/started
// (but not loaded or unloaded).
void FreeLocGlobals() {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK((g_serviceState != SERVICE_STATE_ON) && (g_serviceState != SERVICE_STATE_STARTING_UP));

    // Need to clear out any existing handles at this stage, but do NOT
    // delete this object since we still need it to process LOC_Open()
    // service handles
    g_pHandleMgr->ResetLocHandles();

    if (g_pPluginMgr) {
        delete g_pPluginMgr;
        g_pPluginMgr = NULL;
    }
}

// Takes service from stopped->on state
static DWORD StartLocService(BOOL firstStartup) {
    DEBUGMSG(ZONE_INIT,(L"LOC: Starting Location Framework Service\r\n"));
    DEBUGCHK(g_pLocLock->IsLocked());

    DWORD err;

    if (! firstStartup) {
        // The first time we're started, state=SERVICE_STATE_STARTING_UP.
        // After that, we need to verify we're not already on or shutting down
        // or whatever before begining service startup.
        if (g_serviceState != SERVICE_STATE_OFF) {
            DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Starting service fails because service state must be off, but is instead <%d>\r\n",g_serviceState));
            err = ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
            // Do not cleanup global state in this case.
            goto doneNoCleanup;
        }
        g_serviceState = SERVICE_STATE_STARTING_UP;
    }

    DEBUGCHK(g_serviceState == SERVICE_STATE_STARTING_UP);

    //
    // Initialize global objects 
    //
    g_pPluginMgr = new pluginMgr_t();
    if (g_pPluginMgr == NULL)  {
        DEBUGMSG_OOM();
        err = ERROR_OUTOFMEMORY;
        goto done;
    }

    if (! g_pPluginMgr->IsPlgMgrInited()) {
        // Init normally fails because of some misconfiguration in the system
        // such as the LF registry key not being present.
        err = ERROR_INTERNAL_ERROR;
        goto done;
    }

    err = ERROR_SUCCESS;
    g_serviceState = SERVICE_STATE_ON;
done:
    if (err != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Starting location service failed.  Error=0x%08x\r\n",err));
        g_serviceState = SERVICE_STATE_OFF;
        FreeLocGlobals();
    }
    else
        DEBUGMSG(ZONE_INIT,(L"LOC: Location Framework Service started successfully\r\n"));

doneNoCleanup:
    return err;
}

// Do real work of stopping and starting location framework on a worker
// thread because some plugins may do unsafe operations on PSL thread
// of caller (in particular COM + TLS)
DWORD WINAPI StartLocServiceThread(LPVOID lpv) {
    g_pLocLock->Lock();
    DWORD err = StartLocService((BOOL)lpv);
    DEBUGCHK(g_serviceState==SERVICE_STATE_ON || g_serviceState==SERVICE_STATE_OFF);
    g_pLocLock->Unlock();

    return err;
}

// Takes service from the running state->off/unloading state
static DWORD StopLocService(BOOL unloadService) {
    DEBUGMSG(ZONE_INIT,(L"LOC: Stopping Location Framework Service\r\n"));
    DEBUGCHK(g_pLocLock->IsLocked());

    DWORD err;

    if (unloadService) {
        // When service is requested to unload, then we MUST block until
        // service can be unloaded (and particular until worker threads are stopped)
        // If service was starting up or shutting down already, wait until it is complete
        // before continuing with shutdown

#ifdef DEBUG
		// If it takes more than 20 cycles through loop below to get into a steady
		// state, then something is likely wrong with LF.
		DWORD pollAttempts = 0;
#endif

		while ((g_serviceState != SERVICE_STATE_ON) && (g_serviceState != SERVICE_STATE_OFF)) {
#ifdef DEBUG
			pollAttempts++;
			DEBUGCHK(g_pollRetriesWarnOnUnload != pollAttempts);
#endif
			g_pLocLock->Unlock();
			DEBUGMSG(ZONE_SERVICE,(L"LF: Sleeping <%d> ms on LF unload, waiting to be in state off or state on\r\n",g_pollOnUnload));
			Sleep(g_pollOnUnload);
			g_pLocLock->Lock();
		}
    }
    else {
        // If service is not being unloaded but just stopped (i.e. IOCTL_SERVICE_STOP),
        // then service must be ON in order to proceed.
        if (g_serviceState != SERVICE_STATE_ON) {
            DEBUGMSG(ZONE_ERROR,(L"LOC: ERROR: Attempt to stop service fails since state is not ON, state is <%d>\r\n",g_serviceState));
            err = ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
            goto done;
        }
    }

    g_serviceState = unloadService ? SERVICE_STATE_UNLOADING : SERVICE_STATE_SHUTTING_DOWN;

    FreeLocGlobals();

#ifdef SVSUTIL_DEBUG_THREADS
	// DEBUG verify that that threadpool has no running threads.  
    // Deleting g_pPluginMgr should wait until all workers have stopped.
	SVS_THREAD_POOL_STATS threadPoolStats;
	g_pThreadPool->GetStatistics(&threadPoolStats);
	DEBUGCHK(threadPoolStats.cThreadsRunning == 0);
#endif

    // The thread pool may have idle worker threads still available.
    // Make these close down now also.  This is needed because on a service
    // DeInit(), the thread pool will try to destroy these threads which
    // can lead to deadlock should we be trying this in DllMain().
    g_pThreadPool->Shutdown();
    g_pThreadPool->Reset();

    if (!unloadService)
        g_serviceState = SERVICE_STATE_OFF;

    err = ERROR_SUCCESS;
done:
    return err;
}

// Stop location framework on a worker thread in services.exe --
// see StartLocServiceThread comments
DWORD WINAPI StopLocServiceThread(LPVOID lpv) {
    g_pLocLock->Lock();
    DWORD err = StopLocService((BOOL)lpv);
#ifdef DEBUG
    if (lpv) { // unloading service
        DEBUGCHK(g_serviceState==SERVICE_STATE_UNLOADING);
    }
    else {
        DEBUGCHK(g_serviceState==SERVICE_STATE_ON || g_serviceState==SERVICE_STATE_OFF);
    }
#endif
    g_pLocLock->Unlock();

    return err;
}

// Refresh location framework on a worker thread in services.exe --
// see StartLocServiceThread comments
DWORD WINAPI RefreshLocServiceThread(LPVOID lpv) {
    g_pLocLock->Lock();
    DEBUGMSG(ZONE_INIT,(L"LOC: Refreshing Location Framework Service\r\n"));
    DWORD err = StopLocService(FALSE);
    if (err == ERROR_SUCCESS)
        err = StartLocService(FALSE);

    g_pLocLock->Unlock();
    return err;
}

// Spin up a thread with the specified function, blocking until it has completed.
BOOL LocationSpinThreadAndWait(PFN_LOCATION_THREAD pFunc, LPVOID lpv) {
    DEBUGCHK(! g_pLocLock->IsLocked());
    HANDLE hThread = CreateThread(NULL,0,pFunc,lpv,0,NULL);

    if (! hThread) {
        DEBUGMSG(ZONE_ERROR,(L"LOCATION: CreateThread failed, GLE=<0x%08x>\r\n",GetLastError()));
        return ERROR_OUTOFMEMORY;
    }

    DWORD err;
    WaitForSingleObject(hThread,INFINITE);

    if (! GetExitCodeThread(hThread,&err)) { 
        DEBUGMSG(ZONE_ERROR,(L"LOCATION: GetExitCodeThread failed, GLE=<0x%08x>\r\n",GetLastError()));
        DEBUGCHK(0); // Something is seriously wrong with system or services.exe itself
        err = ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
    }

    if (err != ERROR_SUCCESS)
        SetLastError(err);

    CloseHandle(hThread);
    return (err==ERROR_SUCCESS);
}




// Implements IOCTL_SERVICE_STATUS processing.
BOOL GetServiceStatus(PBYTE pBufOut, DWORD lenOut, DWORD *pActualLenOut) {
    DEBUGCHK(g_pLocLock->IsLocked());
    if (!pBufOut || lenOut < sizeof(DWORD)) {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    __try {
        *(DWORD *)pBufOut = g_serviceState;
        if (pActualLenOut)
            *pActualLenOut = sizeof(DWORD);
    }
    __except (REPORT_EXCEPTION_TO_WATSON()) {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    return TRUE;
}


// 
//  Handeling of user mode APIs calls
//

BOOL LocationOpenIntrnl(
    serviceHandle_t *pServiceHandle, 
    DWORD version, 
    ce::PSL_HANDLE pReserved, // No PSL marshalling of pReserved since it's only checked vs NULL
    DWORD flags, 
    ce::marshal_arg<ce::copy_out,ce::PSL_HANDLE *> phOutHandle
) 
{
    DEBUGMSG(ZONE_API,(L"LOC: LocationOpen(0x%08x,0x%08x,0x%08x) called\r\n",version,pReserved,flags));
    DEBUGCHK(g_pLocLock->IsLocked());

    if (version != LOCATION_FRAMEWORK_VERSION_1) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: LocationOpen() failed because version = <%d>, not required <%d>\r\n",version,LOCATION_FRAMEWORK_VERSION_1));
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    if ((pReserved != 0) || (flags != 0)) {
        // pReserved is a PSL_HANDLE because a VOID* because certain VOID* non-NULL vals may get 
        // marshalled as NULL by the PSL marshaller templates.
        DEBUGMSG(ZONE_ERROR,(L"LOC: LocationOpen() failed because pReserved and/or flags are defined\r\n"));
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    if (phOutHandle == NULL) {
        DEBUGMSG(ZONE_ERROR,(L"LOC: LocationOpen() failed because phOutHandle is NULL\r\n"));
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    HLOCATION h = g_pHandleMgr->AllocLocationHandle(pServiceHandle);
    if (h == 0)
        return FALSE; // Caller SetLastError()

    *phOutHandle = (ce::PSL_HANDLE)h;

    DEBUGMSG(ZONE_API,(L"LOC: LocationOpen succeeded.  New Location Handle = <0x%08x>\r\n",h));
    return TRUE;
}


BOOL LocationCloseIntrnl(
    serviceHandle_t *pServiceHandle, 
    ce::PSL_HANDLE hLocation
) 
{
    DEBUGMSG(ZONE_API,(L"LOC: LocationClose(0x%08x) called\r\n",hLocation));
    DEBUGCHK(g_pLocLock->IsLocked());

    return (ERROR_SUCCESS == g_pHandleMgr->FreeLocationHandle((HLOCATION)hLocation));
}


⌨️ 快捷键说明

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