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

📄 logger.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++

Module Name:  

Abstract:  
 This file implements the NK kernel logging support.

Functions:


Notes: 

--*/
#define C_ONLY
#include "kernel.h"
#include "altimports.h"


// Pointers to the current DLL entry points.
// No DLLs loaded: These will be NULL.
// Only a single DLL loaded: These will be the entry points for that DLL.
// More than one DLL loaded: These will be the broadcast functions.
// These pointers are not strictly necessary since the list could be used to
// figure everything out, but they make the accesses faster.
void (*g_pfnCeLogData)();           // Receives CeLogData calls
static PFNVOID g_pfnCeLogInterrupt;        // Receives CeLogInterrupt calls
// Cannot use a global pointer for CeLogSetZones because we always need to
// use the broadcast function, in order to recalculate zones
static DWORD   g_dwCeLogTimerFrequency;    // Most recent nonzero timer frequency

// The overall zones are a union of all DLL zone settings
static DWORD g_dwZoneUser;
static DWORD g_dwZoneCE;
static DWORD g_dwZoneProcess;


// List of active DLLs
typedef struct CeLogDLLInfo_t {
    struct CeLogDLLInfo_t *pNext;     // The next DLL in the list
    // Pointers to the export functions and data
    PFNVOID pfnCeLogData;             // Receives CeLogData calls      (REQUIRED)
    PFNVOID pfnCeLogInterrupt;        // Receives CeLogInterrupt calls (OPTIONAL)
    PFNVOID pfnCeLogSetZones;         // Receives CeLogSetZones calls  (OPTIONAL)
    FARPROC pfnCeLogQueryZones;       // Receives CeLogGetZones calls, minus last param (OPTIONAL)
    DWORD   dwCeLogTimerFrequency;    // Less than or equal to QueryPerformanceFrequency()
    // Zone info for this DLL
    DWORD   dwZoneUser;
    DWORD   dwZoneCE;
    DWORD   dwZoneProcess;
    } CeLogDLLInfo;
static CeLogDLLInfo *g_pCeLogList;    // The head of the list
static DWORD g_dwCeLogDLLCount;       // Number of DLLs in the list

// Using a type 2 heap object to track this info
ERRFALSE(sizeof(CeLogDLLInfo) <= HEAP_SIZE2);


// Simple protection around CeLog DLL registration; calls will simply fail
// instead of block if they can't get the "CS"
static DWORD g_dwCeLogRegisterCS;

// Set by the TLB miss handler
DWORD dwCeLogTLBMiss;

// OEM can override these globals to control CeLog behavior
DWORD dwCeLogLargeBuf;
DWORD dwCeLogSmallBuf;

// AppVerifier shim globals
PFN_SHIMINITMODULE     g_pfnShimInitModule;
PFN_SHIMWHICHMOD       g_pfnShimWhichMod;
PFN_SHIMUNDODEPENDS    g_pfnShimUndoDepends;
PFN_SHIMIOCONTROL      g_pfnShimIoControl;
PFN_SHIMGETPROCMODLIST g_pfnShimGetProcModList;
PFN_SHIMCLOSEMODULE    g_pfnShimCloseModule;
PFN_SHIMCLOSEPROCESS   g_pfnShimCloseProcess;




//------------------------------------------------------------------------------
//
//
//  APPVERIFIER SHIM DLL REGISTRATION
//
//
//------------------------------------------------------------------------------

BOOL FreeOneLibrary (PMODULE, BOOL);
extern CRITICAL_SECTION ModListcs;


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL KernelLibIoControl_Verifier(
    DWORD   dwIoControlCode,
    LPVOID  lpInBuf,
    DWORD   nInBufSize,
    LPVOID  lpOutBuf,
    DWORD   nOutBufSize,
    LPDWORD lpBytesReturned
    )
{
    switch (dwIoControlCode) {
        case IOCTL_VERIFIER_IMPORT: {
            VerifierImportTable *pImports = (VerifierImportTable*)lpInBuf;

            extern const PFNVOID Win32Methods[];
            extern void* KmodeEntries(void);

//            extern const PFNVOID ExtraMethods[];

            if ((nInBufSize != sizeof(VerifierImportTable))
                || (pImports->dwVersion != VERIFIER_IMPORT_VERSION)) {
                KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
                return FALSE;
            }

            pImports->dwVersion       = VERIFIER_IMPORT_VERSION;
            pImports->pWin32Methods   = (FARPROC*) Win32Methods;
            pImports->NKDbgPrintfW    = (FARPROC) NKDbgPrintfW;
            pImports->pExtraMethods = (FARPROC*) KmodeEntries();
            pImports->pKData          = &KData;
            pImports->KAsciiToUnicode = (FARPROC) KAsciiToUnicode;
            pImports->LoadOneLibraryW = (FARPROC) LoadOneLibraryW;
            pImports->FreeOneLibrary = (FARPROC) FreeOneLibrary;
            pImports->AllocMem = (FARPROC) AllocMem;
            pImports->FreeMem = (FARPROC) FreeMem;
            pImports->AllocName = (FARPROC) AllocName;
            pImports->InitializeCriticalSection = (FARPROC) InitializeCriticalSection;
            pImports->EnterCriticalSection = (FARPROC) EnterCriticalSection;
            pImports->LeaveCriticalSection = (FARPROC) LeaveCriticalSection;
            pImports->pModListcs = & ModListcs;

            break;
        }
        case IOCTL_VERIFIER_REGISTER: {
            VerifierExportTable *pExports = (VerifierExportTable*)lpInBuf;

            if ((nInBufSize != sizeof(VerifierExportTable))
                || (pExports->dwVersion != VERIFIER_EXPORT_VERSION)) {
                KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
                return FALSE;
            }

            // Hook up the logging function pointers
            g_pfnShimInitModule     = (PFN_SHIMINITMODULE)     pExports->pfnShimInitModule;
            g_pfnShimWhichMod       = (PFN_SHIMWHICHMOD)       pExports->pfnShimWhichMod;
            g_pfnShimUndoDepends    = (PFN_SHIMUNDODEPENDS)    pExports->pfnShimUndoDepends;
            g_pfnShimIoControl      = (PFN_SHIMIOCONTROL)      pExports->pfnShimIoControl;
            g_pfnShimGetProcModList = (PFN_SHIMGETPROCMODLIST) pExports->pfnShimGetProcModList;
            g_pfnShimCloseModule    = (PFN_SHIMCLOSEMODULE)    pExports->pfnShimCloseModule;
            g_pfnShimCloseProcess   = (PFN_SHIMCLOSEPROCESS)   pExports->pfnShimCloseProcess;

            break;
        }
        default:
            if (g_pfnShimIoControl) {
                return g_pfnShimIoControl (dwIoControlCode, lpInBuf, nInBufSize, lpOutBuf, nOutBufSize, lpBytesReturned);
            }
            return FALSE;
    }

    return TRUE;
}





//------------------------------------------------------------------------------
//
//
//  CELOG DLL REGISTRATION
//
//
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static _inline BOOL EnterCeLogRegisterCS()
{
    // Cannot use true critical sections to protect registration because they
    // would generate calls into CeLog.  Instead the caller does not block, it
    // simply fails if it cannot get the CS.
    if (InterlockedCompareExchange(&g_dwCeLogRegisterCS, 1, 0) == 0) {
        return TRUE;
    }
    
    KSetLastError(pCurThread, ERROR_SHARING_VIOLATION);
    return FALSE;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static _inline VOID LeaveCeLogRegisterCS()
{
    g_dwCeLogRegisterCS = 0;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Add a DLL to the list and recalculate globals
static BOOL AddCeLogDLL(
    CeLogExportTable *pExports
    )
{
    CeLogDLLInfo *pDLL;
    
    // Check whether it is already registered.  We could use a refcount to
    // allow multiple loads for the same struct but as of now there's no need
    // to be that sophisticated.
    for (pDLL = g_pCeLogList; pDLL; pDLL = pDLL->pNext) {
        if ((pDLL->pfnCeLogData == pExports->pfnCeLogData)
            && (pDLL->pfnCeLogInterrupt == pExports->pfnCeLogInterrupt)
            && (pDLL->pfnCeLogSetZones == pExports->pfnCeLogSetZones)
            && (pDLL->pfnCeLogQueryZones == pExports->pfnCeLogQueryZones)) {
            KSetLastError(pCurThread, ERROR_ALREADY_EXISTS);
            return FALSE;
        }
    }
    
    // CeLogData export is required; all others are optional
    if (pExports->pfnCeLogData == NULL) {
        KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    // Alloc a new struct to hold the DLL info
    pDLL = AllocMem(HEAP_CELOGDLLINFO);
    if (!pDLL) {
        KSetLastError(pCurThread, ERROR_OUTOFMEMORY);
        return FALSE;
    }

    pDLL->pfnCeLogData          = pExports->pfnCeLogData;
    pDLL->pfnCeLogInterrupt     = pExports->pfnCeLogInterrupt;
    pDLL->pfnCeLogSetZones      = pExports->pfnCeLogSetZones;
    pDLL->pfnCeLogQueryZones    = pExports->pfnCeLogQueryZones;
    pDLL->dwCeLogTimerFrequency = pExports->dwCeLogTimerFrequency;

    // Set global timer frequency if necessary
    if (pDLL->dwCeLogTimerFrequency != 0) {
        DEBUGMSG(g_dwCeLogTimerFrequency
                 && (g_dwCeLogTimerFrequency != pDLL->dwCeLogTimerFrequency),
                 (TEXT("CeLog: Timer frequency changing from 0x%08x to 0x%08x\r\n"),
                  g_dwCeLogTimerFrequency, pDLL->dwCeLogTimerFrequency));
        g_dwCeLogTimerFrequency = pDLL->dwCeLogTimerFrequency;
    }

    // Query the DLL zone settings
    if (pDLL->pfnCeLogQueryZones) {
        pDLL->pfnCeLogQueryZones(&(pDLL->dwZoneUser), &(pDLL->dwZoneCE), &(pDLL->dwZoneProcess));
    } else {
        pDLL->dwZoneUser    = 0;
        pDLL->dwZoneCE      = 0;
        pDLL->dwZoneProcess = 0;
    }
    
    // Add the DLL's zones to the global zone settings
    g_dwZoneUser    |= pDLL->dwZoneUser;
    g_dwZoneCE      |= pDLL->dwZoneCE;
    g_dwZoneProcess |= pDLL->dwZoneProcess;
        
    // Add to the head of the list
    pDLL->pNext = g_pCeLogList;
    g_pCeLogList = pDLL;
    g_dwCeLogDLLCount++;

    return TRUE;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Remove a DLL from the list and recalculate globals
static BOOL
RemoveCeLogDLL(
    CeLogExportTable *pExports
    )
{
    CeLogDLLInfo *pDLL, *pPrevDLL;
    BOOL fFound = FALSE;
    
    // We will have to walk the whole list to recalculate the zones and timer freq
    g_dwZoneUser = 0;
    g_dwZoneCE = 0;
    g_dwZoneProcess = 0;
    if ((pExports->dwCeLogTimerFrequency != 0)
        && (g_dwCeLogTimerFrequency == pExports->dwCeLogTimerFrequency)) {
        g_dwCeLogTimerFrequency = 0;
    }

    pPrevDLL = NULL;
    pDLL = g_pCeLogList;
    while (pDLL) {

        if (!fFound
            && (pDLL->pfnCeLogData == pExports->pfnCeLogData)
            && (pDLL->pfnCeLogInterrupt == pExports->pfnCeLogInterrupt)
            && (pDLL->pfnCeLogSetZones == pExports->pfnCeLogSetZones)
            && (pDLL->pfnCeLogQueryZones == pExports->pfnCeLogQueryZones)) {

            CeLogDLLInfo *pTemp = pDLL;  // temp holder

            // Found it
            fFound = TRUE;

            // Remove from the list
            if (pPrevDLL == NULL) {
                // Removing the head of the list
                g_pCeLogList = pDLL->pNext;
            } else {
                pPrevDLL->pNext = pDLL->pNext;
            }
            g_dwCeLogDLLCount--;
            
            // Continue iteration -- pPrevDLL does not change
            pDLL = pDLL->pNext;

            // Free the DLL info
            if (IsValidKPtr(pTemp)) {
                FreeMem(pTemp, HEAP_CELOGDLLINFO);
            }
            
        } else {
            // Add the DLL's zones to the global zone settings
            g_dwZoneUser    |= pDLL->dwZoneUser;
            g_dwZoneCE      |= pDLL->dwZoneCE;
            g_dwZoneProcess |= pDLL->dwZoneProcess;
            
            // Use the first nonzero timer frequency in the list
            if ((g_dwCeLogTimerFrequency == 0) && (pDLL->dwCeLogTimerFrequency != 0)) {
                DEBUGMSG(pExports->dwCeLogTimerFrequency
                         && (pExports->dwCeLogTimerFrequency != pDLL->dwCeLogTimerFrequency),
                         (TEXT("CeLog: Timer frequency changing from 0x%08x to 0x%08x\r\n"),
                          pExports->dwCeLogTimerFrequency, pDLL->dwCeLogTimerFrequency));
                g_dwCeLogTimerFrequency = pDLL->dwCeLogTimerFrequency;
            }

            pPrevDLL = pDLL;
            pDLL = pDLL->pNext;
        }
    }

    if (!fFound) {
        KSetLastError(pCurThread, ERROR_MOD_NOT_FOUND);
        return FALSE;
    }
    
    return TRUE;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static void 
BroadcastCeLogData( 
    BOOL  fTimeStamp,
    WORD  wID,
    VOID  *pData,
    WORD  wLen,
    DWORD dwZoneUser,
    DWORD dwZoneCE,
    WORD  wFlag,
    BOOL  fFlagged
    )
{
    CeLogDLLInfo *pDLL;
    
    for (pDLL = g_pCeLogList; pDLL; pDLL = pDLL->pNext) {
        pDLL->pfnCeLogData(fTimeStamp, wID, pData, wLen, dwZoneUser, dwZoneCE,
                           wFlag, fFlagged);
    }
}


#ifdef NKPROF

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static void
BroadcastCeLogInterrupt( 
    DWORD dwLogValue
    )
{
    CeLogDLLInfo *pDLL;
    
    for (pDLL = g_pCeLogList; pDLL; pDLL = pDLL->pNext) {
        if (pDLL->pfnCeLogInterrupt) {
            pDLL->pfnCeLogInterrupt(dwLogValue);
        }
    }
}

#endif  // NKPROF


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

⌨️ 快捷键说明

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