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

📄 printf.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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.
//
/*
 *              NK Kernel printf code
 *
 *
 * Module Name:
 *
 *              printf.c
 *
 * Abstract:
 *
 *              This file implements debug and string routines
 *
 */
 
/*
@doc    EXTERNAL KERNEL
@topic  Debug Support for Applications | 
    The kernel provides several kinds of supports for debugging
    applications. These are:
    
    <b Debug Messages>: The kernel provides API's for printing out
    of debug messages which can be turned on and off dynamically 
    using zones. Any module (DLL/Process) can register itself
    with the debug subsystem using <f DEBUGREGISTER>. This API
    registers the address of a Zonemask (which is a DWORD) with the
    kernel. Using the debug shell, a user can now dynamically turn
    bits of this zonemask on and off from the shell window.        
    The most typical way to use this is to filter debug messages
    based on these bits. A structured way to do this is to use
    the <f DEBUGZONE> macro to associate zones with bits, and then
    use the <f DEBUGMSG> function to associate each debug message
    with a zone. Type ? in the shell to see how to change zones 
    dynamically from the shell which uses the <f SetDbgZone> function
    to implement the change. See the example below for general zone
    usage.
    
    <b Asserts>: The kernel also provides for simple asserts. See
    <f DEBUGCHK> for details.
    
@ex     An example of using debug zones |
    // Declare a DBGPARAM structure & give names to all used zones
    DBGPARAM dpCurSettings = { L"foodll", {
        L"Info",       L"Validate",  L"bar",       L"random",
        L"Undefined",  L"Undefined", L"Undefined", L"Undefined",
        L"Undefined",  L"Undefined", L"Undefined", L"Undefined",
        L"Undefined",  L"Undefined", L"Undefined", L"Undefined" },
        0x00000000 };
        
    // Associate bits with a zone 
    // these should match up with the text strings above!
    #define ZONE_INFO       DEBUGZONE(0)
    #define ZONE_VALIDATE   DEBUGZONE(1)

    // Register : Assume this is a DLL 
    // A Process would do the same in their libmain
    BOOL DllEntry (HANDLE hinstDLL, DWORD fdwReason, LPVOID lpv) {
        if ( fdwReason == DLL_PROCESS_ATTACH ) {
        DEBUGREGISTER(hinstDLL);
        }
        ...
    }

    // Use the defined zone in debug messages
    DEBUGMSG (ZONE_INFO, (L"This is an illustrative messages only!"));

    // Or use a zone to turn execution of some code on & off
    if (ZONE_VALIDATE) {
        // validate some stuff ...
    }            
            
@xref   
    <f DEBUGMSG> <tab> <f RETAILMSG> <tab> <f ERRORMSG> <tab> <f DEBUGCHK> <tab>
    <f DEBUGREGISTER> <tab> <f DEBUGZONE> <tab> <t DBGPARAM> <tab>
    <f RegisterDebugZones> <tab> <f SetDbgZone>
*/ 

#include "kernel.h"

#define out(c) if (--cchLimit) *lpOut++=(c); else goto errorout

//-------------------------- Prototype declarations ---------------------------

int NKwvsprintfW(LPWSTR lpOut, LPCWSTR lpFmt, CONST VOID * lpParms, int maxchars);
LPCWSTR SP_GetFmtValue(LPCWSTR lpch, int  *lpw, va_list *plpParms);
int SP_PutNumber(LPWSTR, ULONG, int, int, int);
int SP_PutNumber64(LPWSTR lpb, __int64 i64, int limit, int radix, int mycase);
void SP_Reverse(LPWSTR lp1, LPWSTR lp2);

extern CRITICAL_SECTION ODScs, DbgApiCS, VAcs, PhysCS;

extern BOOL fSysStarted;
extern BOOL g_cInterruptsOff;    // this indicates KD had turned interrupts off


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
VOID WINAPI 
OutputDebugStringW(
    LPCWSTR str
    ) 
{
    BOOL fGetODScs = FALSE, fLockPages = FALSE;
    int len;

    // if we ever call OutputDebugString with interrupts off, send it to serial
    // port and return right away
    if (g_cInterruptsOff) {
        OEMWriteDebugString((unsigned short *)str);
        return;
    }

    // increase debug count to indicate we're in ODS
    if (!str)
        str = __TEXT("(NULL)");

    if (pCurThread) {

        pCurThread->bDbgCnt ++;

        // do not notify debugger while in power handler because we cannot block
        if (!InSysCall () && !IsInPwrHdlr ()) {
        
            if (pCurThread->pThrdDbg && (DbgApiCS.OwnerThread != hCurThread)  
                && ProcStarted(pCurProc) && pCurThread->pThrdDbg->hEvent) {
                pCurThread->pThrdDbg->dbginfo.dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
                pCurThread->pThrdDbg->dbginfo.dwProcessId = (DWORD)hCurProc;
                pCurThread->pThrdDbg->dbginfo.dwThreadId = (DWORD)hCurThread;
                pCurThread->pThrdDbg->dbginfo.u.DebugString.lpDebugStringData = (LPBYTE)str;
                pCurThread->pThrdDbg->dbginfo.u.DebugString.fUnicode = TRUE;
                pCurThread->pThrdDbg->dbginfo.u.DebugString.nDebugStringLength = (strlenW(str)+1)*2;
                SetEvent(pCurThread->pThrdDbg->hEvent);
                SC_WaitForMultiple(1,&pCurThread->pThrdDbg->hBlockEvent,FALSE,INFINITE);
            }
            
            fGetODScs = !ReadyForStrings && (hCurThread != ODScs.OwnerThread);
            fLockPages = (1 == pCurThread->bDbgCnt);

        }
    }
    
    // forces the string to be paged in if not already
    len = (strlenW(str)+1)*sizeof(WCHAR);

    // Lock page if we need to
    if (fLockPages)
        LockPages((LPVOID)str,len,0,0);

    if (fGetODScs)
        EnterCriticalSection(&ODScs);

    lpWriteDebugStringFunc((unsigned short *)str);

    if (fGetODScs)
        LeaveCriticalSection(&ODScs);

    if (fLockPages)
        UnlockPages((LPVOID)str,len);

    // decrement debug count to indicate we're out of ODS
    if (pCurThread) {
        pCurThread->bDbgCnt --;
    }
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int 
InputDebugCharW(void) 
{
    int retvalue;
    if (!InSysCall())
        EnterCriticalSection(&ODScs);
    retvalue = OEMReadDebugByte();
    if (!InSysCall())
        LeaveCriticalSection(&ODScs);
    return retvalue;
}

//------------------------------------------------------------------------------
// special version if we're on KStack
//------------------------------------------------------------------------------
static VOID _NKvDbgPrintfW(LPCWSTR lpszFmt, va_list lpParms) {
    static WCHAR rgchBuf[384];
    NKwvsprintfW(rgchBuf, lpszFmt, lpParms, sizeof(rgchBuf)/sizeof(WCHAR));
    OutputDebugStringW(rgchBuf);
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#if (_MSC_VER >= 1300)
__declspec(noinline) // Too much KStack is used if this is inlined
#endif
static VOID NKvDbgPrintfWOnStack(LPCWSTR lpszFmt, va_list lpParms) 
{
    WCHAR rgchBuf[384];
    WORD wLen = 0;
    // Get it into a string
#ifdef DEBUG
    if (ZONE_DEBUG) {
        rgchBuf[0] = '0';
        rgchBuf[1] = 'x';
        wLen += 2;
        wLen += SP_PutNumber(rgchBuf+2,(ULONG)pCurThread,8,16,0);
        SP_Reverse(rgchBuf+2,rgchBuf+wLen-1);
        rgchBuf[wLen++] = ':';
        rgchBuf[wLen++] = ' ';
    }
#endif
    wLen += NKwvsprintfW(rgchBuf + wLen, lpszFmt, lpParms, sizeof(rgchBuf)/sizeof(WCHAR) - wLen);

    // don't need to call LockPages since it's on stack.
    if (pCurThread) {
        pCurThread->bDbgCnt ++;
    }
    OutputDebugStringW(rgchBuf);
    if (pCurThread) {
        pCurThread->bDbgCnt --;
    }
}


//------------------------------------------------------------------------------
//
//  @doc    EXTERNAL KERNEL
//  @func   VOID | NKDbgPrintf | Prints debug messages
//  @parm   LPWSTR | lpszFmt | Printf style formatting string
//  @parmvar Variable argument list
//  @comm   Should not be used directly - macros like <f DEBUGMSG> should
//      be used to print messages. This function will format the
//      debug string into a buffer and then log it according to the
//      current logging paramters. If terminal logging is on it
//      outputs this to the debug terminal, and if file logging
//      is on it stores it to the file peg.log on the host PC.
//      
//      <b WARNING>: The message being output must be smaller than
//      256 bytes - ie 128 unicode characters.
//  @xref   <f DEBUGMSG>
//
//------------------------------------------------------------------------------
void WINAPIV 
NKDbgPrintfW(
    LPCWSTR lpszFmt,
    ...
    )  
{
    va_list arglist;
    va_start(arglist, lpszFmt);
    NKvDbgPrintfW(lpszFmt, arglist);
    va_end(arglist);
}

VOID NKvDbgPrintfW (LPCWSTR lpszFmt, va_list lpParms) 
{
    if (fSysStarted && !InSysCall ())                NKvDbgPrintfWOnStack (lpszFmt, lpParms);
    else
        _NKvDbgPrintfW(lpszFmt, lpParms);
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int 
NKwvsprintfW(
    LPWSTR lpOut,
    LPCWSTR lpFmt,
    va_list lpParms,
    int maxchars
    ) 
{
    int left, width, prec, size, sign, radix, upper, cch, cchLimit;
    WCHAR prefix, fillch;
    LPWSTR lpT;
    LPCHAR lpC;
    union {
        long l;
        unsigned long ul;
        __int64 i64;
        WCHAR sz[sizeof(long)];
    } val;

    cchLimit = maxchars;
    while (*lpFmt) {
        if (*lpFmt==(WCHAR)'%') {
            /* read the flags.  These can be in any order */
            left=0;
            prefix=0;
            while (*++lpFmt) {

⌨️ 快捷键说明

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