通常我们在BSP下一般使用RETAILMSG这个函数来实现串口打印,某些驱动也用DEBUGMSG。 在OAL又是另外一些串口打印函数。我们很早就知道这是OAL之下的debug.c的串口函数实现的,但是具体是怎么实现的,我从来没有去看过。今天碰到在串口MDD层无法使用串口打印的情况,搞得我很郁闷。就下决心找出来到底是怎么回事。
C:/WINCE500/PUBLIC/COMMON/SDK/INC中的dbgapi.h实现了RETAILMSG和DEBUGMSG,下面来看看到底是怎么回事。
Module Name: dbgapi.h
Module Name: dbgapi.h
Purpose: Debug Message and Zone APIs.
--*/
#ifndef __DBGAPI_H__
#define __DBGAPI_H__
#ifdef __cplusplus
extern "C" {
#endif
void WINAPIV NKDbgPrintfW(LPCWSTR lpszFmt,
);
void WINAPI WriteDebugLED(WORD wIndex, DWORD dwPattern);
/*
@doc EXTERNAL KERNEL
@struct DBGPARAM | Debug zone information structure
@comm The name of the module is used to look for zone initialization
information in the host PC registry. Zone names are displayed by
the control app (eg shell) which allows the user to dynamically
set zones.
@xref <f DEBUGREGISTER>
*/
typedef struct _DBGPARAM {
WCHAR lpszName[32]; // @field Name of module
WCHAR rglpszZones[16][32]; // @field names of zones for first 16 bits
ULONG ulZoneMask; // @field Current zone Mask
} DBGPARAM, *LPDBGPARAM;
BOOL RegisterDbgZones(HMODULE hMod, LPDBGPARAM lpdbgparam);
/*
@func BOOL | DEBUGZONE | Associates a mask bit with a zone
@parm int | bitnum | Bitnumber being defined
@rdesc A boolean which is TRUE if bitnum in '1' else is FALSE
@ex Example of use is |
// associate bit 0 with an info zone
#define ZONE_INFO DEBUGZONE(0)
// we can now use ZONE_INFO as a boolean for anything.
// We'd typically use it in a DEBUGMSG ![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
*/
#define DEBUGZONE(n) (dpCurSettings.ulZoneMask&(0x00000001<<(n)))
#ifdef DEBUG
#ifdef SHIP_BUILD
#undef SHIP_BUILD
#pragma message (__FILE__ ":WARNING: SHIP_BUILD turned off since DEBUG defined")
#endif
#endif
#ifdef SHIP_BUILD //如果定义了SHIP_BUILD 那么以下串口打印函数就不会打印了。这个貌似可以使用环境变量设定。
#define ERRORMSG(cond,printf_exp) ((void)0)
#define RETAILMSG(cond,printf_exp) ((void)0)
#define DEBUGMSG(cond,printf_exp) ((void)0)
#define DEBUGLED(cond,parms) ((void)0)
#define DBGCHK(module,exp) ((void)0)
#define DEBUGCHK(exp) ((void)0)
#define DEBUGREGISTER(hMod) ((void)0)
#define RETAILREGISTERZONES(hMod) ((void)0)
#else // SHIP_BUILD
#ifdef DEBUG //debug模式NK
/*
@func BOOL | DEBUGMSG | Output a debug message conditionally
@parm BOOL | cond | The condition under which the message is printed
@parm <null> | (printf_exp) | A printf style expression to be output. Must be enclosed
in parentheses. Gets passed on to the <f NKDbgPrintf> function.
@ex Example of use |
DEBUGMSG(ZONE_INFO, (L"DLLNAME: Entered func1. Param 1 = %d/r/n", par1));
@xref <f RETAILMSG> <tab> <f ERRORMSG> <tab> <f NKDbgPrintf>
*/
#define DEBUGMSG(cond,printf_exp) /
((void)((cond)?(NKDbgPrintfW printf_exp),1:0)) //DEBUGMSG是通过NKDbgPrintfW 来实现的
#define DBGCHK(module,exp) /
((void)((exp)?1:( /
NKDbgPrintfW ( TEXT("%s: DEBUGCHK failed in file %s at line %d /r/n"), /
(LPWSTR)module, TEXT(__FILE__) ,__LINE__ ), /
DebugBreak(), /
0 /
)))
/*
@func BOOL | DEBUGLED | Output a debug LED pattern conditionally
@parm BOOL | cond | The condition under which the message is printed
@parm <null> | (parms) | The parameters to be passed to the WriteDebugLED
function. Must be in parentheses. First parameter is wIndex and second
parameter is dwPattern.
@ex Example of use |
DEBUGLED(ZONE_INFO, (3, 0x2345);
@xref <f RETAILMSG> <tab> <f ERRORMSG> <tab> <f WriteDebugLED>
*/
#define DEBUGLED(cond,parms) /
((void)((cond)?(WriteDebugLED parms),1:0))
/*
@func BOOL | DEBUGCHK | Asserts an expression
@parm BOOL | exp | Expression to be asserted
@comm If the expression is false, this will cause a DebugBreak to be hit which
will cause you to enter the debugger if you are running with one. It will
also give you the line number and file name where the assert failed.
*/
#define DEBUGCHK(exp) DBGCHK(dpCurSettings.lpszName, exp)
extern DBGPARAM dpCurSettings;
/*
@func BOOL | DEBUGREGISTER | Registers debug settings for a process / module
@parm HINSTANCE | hInstance | If target is a module this is it's hInstance. If
target is a process this should be NULL.
@comm This simply calls through to <f RegisterDebugZones>. It assumes that
there is a variable of name <b dpCurSettings> visible in the code.
*/
#define DEBUGREGISTER(hMod) RegisterDbgZones(hMod, &dpCurSettings)
#else // DEBUG 如果没有定义,就不会打印。
#define DEBUGMSG(cond,printf_exp) ((void)0)
#define DEBUGLED(cond,parms) ((void)0)
#define DBGCHK(module,exp) ((void)0)
#define DEBUGCHK(exp) ((void)0)
#define DEBUGREGISTER(hMod) ((void)0)
#endif // DEBUG
/*
@func BOOL | RETAILMSG | Output a message in retail builds
@parm BOOL | cond | The condition under which the message is printed
@parm <null> | (printf_exp) | A printf style expression to be output. Must be enclosed
in parentheses. This is simply passed in to the <f NKDbgPrintf> function.
@comm This should be used in a very limited fashion since it can increase
the size of your retail build.
@ex Example of use |
RETAILMSG(x==y, (L"DLLNAME: Expect. x==y = %d/r/n", x));
@xref <f DEBUGMSG> <tab> <f ERRORMSG> <tab> <f NKDbgPrintf>
*/
#define RETAILMSG(cond,printf_exp)///从这里可以知道,RETAILMSG、DEBUGMSG一模一样,只是换了名字,通过NKDbgPrintfW来实现的
((cond)?(NKDbgPrintfW printf_exp),1:0)
/*
@func BOOL | ERRORMSG | Output an error msg
@parm BOOL | cond | The condition under which the message is printed
@parm <null> | (printf_exp) | A printf style expression to be output. Must be enclosed
in parentheses. This is passed in to the <f NKDbgPrintf> function.
@comm Very similar to <f RETAILMSG> except that this will prefix the message
with "ERROR" and give the file name & line number of the error.
@ex Example of use |
ERRORMSG(x==y, (L"DLLNAME: x===y = %d/r/n", x));
@xref <f DEBUGMSG> <tab> <f RETAILMSG> <tab> <f NKDbgPrintf>
*/
#define ERRORMSG(cond,printf_exp) /
((cond)?(NKDbgPrintfW(TEXT("ERROR: %s line %d: "),TEXT(__FILE__),__LINE__), NKDbgPrintfW printf_exp),1:0)
/*
@func BOOL | RETAILREGISTERZONES | Registers zone settings for a process / module
(Same as DEBUGREGISTER except available in retail and debug builds)
@parm HINSTANCE | hInstance | If target is a module this is it's hInstance. If
target is a process this should be NULL.
@comm This simply calls through to <f RegisterDebugZones>. It assumes that
there is a variable of name <b dpCurSettings> visible in the code.
*/
#define RETAILREGISTERZONES(hMod) RegisterDbgZones(hMod, &dpCurSettings)
#endif // SHIP_BUILD
/*
@func BOOL | RETAILLED | Output a LED code in retail builds
@parm BOOL | cond | The condition under which the message is printed
@parm <null> | (parms) | The parameters to be passed to the WriteDebugLED
function. Must be in parentheses. First parameter is wIndex and second
parameter is dwPattern.
@comm This should be used in a very limited fashion since it can increase
the size of your retail build.
@ex Example of use |
RETAILLED(ZONE_INFO, (3, 0x2345);
@xref <f DEBUGMSG> <tab> <f ERRORMSG> <tab> <f WriteDebugLED>
*/
#define RETAILLED(cond,parms) /
((void)((cond)?(WriteDebugLED parms),1:0))
// some alternate ways to get to these
#define ASSERTMSG(msg, exp) (DEBUGMSG(!exp,(msg)),DBGCHK(TEXT("Unknown"),exp))
#define ASSERT( exp ) DBGCHK(TEXT("Unknown"), exp)
#define ASSERT_IMPLIES( cond, exp ) ASSERT( !(cond) || (exp) )
#ifdef DEBUG
#define VERIFY(exp) ASSERT(exp)
#else
#define VERIFY(exp) ((void)(exp))
#endif
// Enable providing a hint to prefast via __assume
// e.g.
// PREFAST_ASSUME( pPointer); // we know pPointer can never be NULL
#ifdef _PREFAST_
#define PREFAST_ASSUME(exp) __assume(exp)
#else
#define PREFAST_ASSUME(exp)
#endif
// Simplify the cases where a PREFAST_ASSUME would be followed by an assertion
#define PREFAST_DEBUGCHK(exp) /
{ /
PREFAST_ASSUME(exp); /
DEBUGCHK(exp); /
}
#define PREFAST_ASSERT(exp) /
{ /
PREFAST_ASSUME(exp); /
ASSERT(exp); /
}
// macro to tell Prefast to not issue a specific warning for the following line of code
// use to suppress false positives from Prefast
// e.g.
// if( fPointerNotNull )
// PREFAST_SUPPRESS( 11, "pointer access is guarded by 'fPointerNotNull'" )
// p->Foo();
#ifdef _PREFAST_
#define PREFAST_SUPPRESS( cWarning, comment) __pragma ( prefast(suppress: cWarning, comment) )
#else
#define PREFAST_SUPPRESS( cWarning, comment)
#endif
// Helpful DBG macros that tighten up code.
// They prepend __FUNCTION__ to your debug msg and add a /n to the end.
#define DEB_0(ZONE,STR) DEBUGMSG(ZONE,(L"%S:"STR L"/n",__FUNCTION__))
#define DEB_1(ZONE,STR,ARG1) DEBUGMSG(ZONE,(L"%S:"STR L"/n",__FUNCTION__,ARG1))
#define DEB_2(ZONE,STR,ARG1,ARG2) DEBUGMSG(ZONE,(L"%S:"STR L"/n",__FUNCTION__,ARG1,ARG2))
#define DEB_3(ZONE,STR,ARG1,ARG2,ARG3) DEBUGMSG(ZONE,(L"%S:"STR L"/n",__FUNCTION__,ARG1,ARG2,ARG3))
#define DEB_4(ZONE,STR,ARG1,ARG2,ARG3,ARG4) DEBUGMSG(ZONE,(L"%S:"STR L"/n",__FUNCTION__,ARG1,ARG2,ARG3,ARG4))
#define DEB_5(ZONE,STR,ARG1,ARG2,ARG3,ARG4,ARG5) DEBUGMSG(ZONE,(L"%S:"STR L"/n",__FUNCTION__,ARG1,ARG2,ARG3,ARG4,ARG5))
//
// The _A version of the above are identical, except they call assert after the DEB_*.
// It's highly recommend that you use DEB_*_A with ZONE_ERROR so the user can always see the error.
// printed with the assert.
// NOTE: The assert is not conditioned on the ZONE.
#define DEB_0_A(ZONE,STR) { DEB_0(ZONE,STR);ASSERT(FALSE); }
#define DEB_1_A(ZONE,STR,ARG1) { DEB_1(ZONE,STR,ARG1); ASSERT(FALSE);}
#define DEB_2_A(ZONE,STR,ARG1,ARG2) { DEB_2(ZONE,STR,ARG1,ARG2); ASSERT(FALSE);}
#define DEB_3_A(ZONE,STR,ARG1,ARG2,ARG3) { DEB_3(ZONE,STR,ARG1,ARG2,ARG3); ASSERT(FALSE);}
#define DEB_4_A(ZONE,STR,ARG1,ARG2,ARG3,ARG4) { DEB_4(ZONE,STR,ARG1,ARG2,ARG3,ARG4); ASSERT(FALSE);}
#define DEB_5_A(ZONE,STR,ARG1,ARG2,ARG3,ARG4,ARG5) {DEB_5(ZONE,STR,ARG1,ARG2,ARG3,ARG4,ARG5); ASSERT(FALSE);}
#ifdef __cplusplus
}
#endif
#endif
从上面可以知道,RETAILMSG、DEBUGMSG一模一样,只是换了名字,通过NKDbgPrintfW来实现的,那么这个NKDbgPrintfW又是怎么来的呢?
NKDbgPrintfW
1
//
2
// Copyright (c) Microsoft Corporation. All rights reserved.
3
//
4
//
5
// This source code is licensed under Microsoft Shared Source License
6
// Version 1.0 for Windows CE.
7
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
8
//
9![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
/**//*
10
* NK Kernel printf code
11
*
12
*
13
* Module Name:
14
*
15
* printf.c
16
*
17
* Abstract:
18
*
19
* This file implements debug and string routines
20
*
21
*/
22
23![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
/**//*
24
@doc EXTERNAL KERNEL
25
@topic Debug Support for Applications |
26
The kernel provides several kinds of supports for debugging
27
applications. These are:
28
29
<b Debug Messages>: The kernel provides API's for printing out
30
of debug messages which can be turned on and off dynamically
31
using zones. Any module (DLL/Process) can register itself
32
with the debug subsystem using <f DEBUGREGISTER>. This API
33
registers the address of a Zonemask (which is a DWORD) with the
34
kernel. Using the debug shell, a user can now dynamically turn
35
bits of this zonemask on and off from the shell window.
36
The most typical way to use this is to filter debug messages
37
based on these bits. A structured way to do this is to use
38
the <f DEBUGZONE> macro to associate zones with bits, and then
39
use the <f DEBUGMSG> function to associate each debug message
40
with a zone. Type ? in the shell to see how to change zones
41
dynamically from the shell which uses the <f SetDbgZone> function
42
to implement the change. See the example below for general zone
43
usage.
44
45
<b Asserts>: The kernel also provides for simple asserts. See
46
<f DEBUGCHK> for details.
47
48
@ex An example of using debug zones |
49
// Declare a DBGPARAM structure & give names to all used zones
50
DBGPARAM dpCurSettings = { L"foodll", {
51
L"Info", L"Validate", L"bar", L"random",
52
L"Undefined", L"Undefined", L"Undefined", L"Undefined",
53
L"Undefined", L"Undefined", L"Undefined", L"Undefined",
54
L"Undefined", L"Undefined", L"Undefined", L"Undefined" },
55
0x00000000 };
56
57
// Associate bits with a zone
58
// these should match up with the text strings above!
59
#define ZONE_INFO DEBUGZONE(0)
60
#define ZONE_VALIDATE DEBUGZONE(1)
61![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
62
// Register : Assume this is a DLL
63
// A Process would do the same in their libmain
64
BOOL DllEntry (HANDLE hinstDLL, DWORD fdwReason, LPVOID lpv) {
65
if ( fdwReason == DLL_PROCESS_ATTACH ) {
66
DEBUGREGISTER(hinstDLL);
67
}
68
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
69
}
70![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
71
// Use the defined zone in debug messages
72
DEBUGMSG (ZONE_INFO, (L"This is an illustrative messages only!"));
73![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
74
// Or use a zone to turn execution of some code on & off
75
if (ZONE_VALIDATE) {
76
// validate some stuff ![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
77
}
78
79
@xref
80
<f DEBUGMSG> <tab> <f RETAILMSG> <tab> <f ERRORMSG> <tab> <f DEBUGCHK> <tab>
81
<f DEBUGREGISTER> <tab> <f DEBUGZONE> <tab> <t DBGPARAM> <tab>
82
<f RegisterDebugZones> <tab> <f SetDbgZone>
83
*/
84![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
85
#include "kernel.h"
86![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
87
#define out(c) if (--cchLimit) *lpOut++=(c); else goto errorout
88![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
89
//-------------------------- Prototype declarations ---------------------------
90![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
91
int NKwvsprintfW(LPWSTR lpOut, LPCWSTR lpFmt, CONST VOID * lpParms, int maxchars);
92
LPCWSTR SP_GetFmtValue(LPCWSTR lpch, int *lpw, va_list *plpParms);
93
int SP_PutNumber(LPWSTR, ULONG, int, int, int);
94
int SP_PutNumber64(LPWSTR lpb, __int64 i64, int limit, int radix, int mycase);
95
void SP_Reverse(LPWSTR lp1, LPWSTR lp2);
96![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
97
extern CRITICAL_SECTION ODScs, DbgApiCS, VAcs, PhysCS;
98![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
99
extern BOOL fSysStarted;
100
extern BOOL g_cInterruptsOff; // this indicates KD had turned interrupts off
101![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
102![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
103
//------------------------------------------------------------------------------
104
//------------------------------------------------------------------------------
105
VOID WINAPI
106
OutputDebugStringW(
107
LPCWSTR str
108
)
109![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
110
BOOL fGetODScs = FALSE, fLockPages = FALSE;
111
int len;
112![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
113
// if we ever call OutputDebugString with interrupts off, send it to serial
114
// port and return right away
115![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (g_cInterruptsOff)
{
116
OEMWriteDebugString((unsigned short *)str);
117
return;
118
}
119![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
120
// increase debug count to indicate we're in ODS
121
if (!str)
122
str = __TEXT("(NULL)");
123![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
124![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (pCurThread)
{
125![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
126
pCurThread->bDbgCnt ++;
127![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
128
// do not notify debugger while in power handler because we cannot block
129![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (!InSysCall () && !IsInPwrHdlr ())
{
130
131
if (pCurThread->pThrdDbg && (DbgApiCS.OwnerThread != hCurThread)
132![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
&& ProcStarted(pCurProc) && pCurThread->pThrdDbg->hEvent)
{
133
pCurThread->pThrdDbg->dbginfo.dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
134
pCurThread->pThrdDbg->dbginfo.dwProcessId = (DWORD)hCurProc;
135
pCurThread->pThrdDbg->dbginfo.dwThreadId = (DWORD)hCurThread;
136
pCurThread->pThrdDbg->dbginfo.u.DebugString.lpDebugStringData = (LPBYTE)str;
137
pCurThread->pThrdDbg->dbginfo.u.DebugString.fUnicode = TRUE;
138
pCurThread->pThrdDbg->dbginfo.u.DebugString.nDebugStringLength = (strlenW(str)+1)*2;
139
SetEvent(pCurThread->pThrdDbg->hEvent);
140
SC_WaitForMultiple(1,&pCurThread->pThrdDbg->hBlockEvent,FALSE,INFINITE);
141
}
142
143
fGetODScs = !ReadyForStrings && (hCurThread != ODScs.OwnerThread);
144
fLockPages = (1 == pCurThread->bDbgCnt);
145![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
146
}
147
}
148
149
// forces the string to be paged in if not already
150
len = (strlenW(str)+1)*sizeof(WCHAR);
151![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
152
// Lock page if we need to
153
if (fLockPages)
154
LockPages((LPVOID)str,len,0,0);
155![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
156
if (fGetODScs)
157
EnterCriticalSection(&ODScs);
158![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
159
lpWriteDebugStringFunc((unsigned short *)str);
160![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
161
if (fGetODScs)
162
LeaveCriticalSection(&ODScs);
163![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
164
if (fLockPages)
165
UnlockPages((LPVOID)str,len);
166![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
167
// decrement debug count to indicate we're out of ODS
168![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (pCurThread)
{
169
pCurThread->bDbgCnt --;
170
}
171
}
172![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
173![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
174![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
175
//------------------------------------------------------------------------------
176
//------------------------------------------------------------------------------
177
int
178
InputDebugCharW(void)
179![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
180
int retvalue;
181
if (!InSysCall())
182
EnterCriticalSection(&ODScs);
183
retvalue = OEMReadDebugByte();
184
if (!InSysCall())
185
LeaveCriticalSection(&ODScs);
186
return retvalue;
187
}
188![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
189
//------------------------------------------------------------------------------
190
// special version if we're on KStack
191
//------------------------------------------------------------------------------
192![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
static VOID _NKvDbgPrintfW(LPCWSTR lpszFmt, va_list lpParms)
{
193
static WCHAR rgchBuf[384];
194
NKwvsprintfW(rgchBuf, lpszFmt, lpParms, sizeof(rgchBuf)/sizeof(WCHAR));
195
OutputDebugStringW(rgchBuf);
196
}
197![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
198
//------------------------------------------------------------------------------
199
//------------------------------------------------------------------------------
200
#if (_MSC_VER >= 1300)
201
__declspec(noinline) // Too much KStack is used if this is inlined
202
#endif
203
static VOID NKvDbgPrintfWOnStack(LPCWSTR lpszFmt, va_list lpParms)
204![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
205
WCHAR rgchBuf[384];
206
WORD wLen = 0;
207
// Get it into a string
208
#ifdef DEBUG
209![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (ZONE_DEBUG)
{
210
rgchBuf[0] = '0';
211
rgchBuf[1] = 'x';
212
wLen += 2;
213
wLen += SP_PutNumber(rgchBuf+2,(ULONG)pCurThread,8,16,0);
214
SP_Reverse(rgchBuf+2,rgchBuf+wLen-1);
215
rgchBuf[wLen++] = ':';
216
rgchBuf[wLen++] = ' ';
217
}
218
#endif
219
wLen += NKwvsprintfW(rgchBuf + wLen, lpszFmt, lpParms, sizeof(rgchBuf)/sizeof(WCHAR) - wLen);
220![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
221
// don't need to call LockPages since it's on stack.
222![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (pCurThread)
{
223
pCurThread->bDbgCnt ++;
224
}
225
OutputDebugStringW(rgchBuf);
226![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (pCurThread)
{
227
pCurThread->bDbgCnt --;
228
}
229
}
230![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
231![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
232
//------------------------------------------------------------------------------
233
//
234
// @doc EXTERNAL KERNEL
235
// @func VOID | NKDbgPrintf | Prints debug messages
236
// @parm LPWSTR | lpszFmt | Printf style formatting string
237
// @parmvar Variable argument list
238
// @comm Should not be used directly - macros like <f DEBUGMSG> should
239
// be used to print messages. This function will format the
240
// debug string into a buffer and then log it according to the
241
// current logging paramters. If terminal logging is on it
242
// outputs this to the debug terminal, and if file logging
243
// is on it stores it to the file peg.log on the host PC.
244
//
245
// <b WARNING>: The message being output must be smaller than
246
// 256 bytes - ie 128 unicode characters.
247
// @xref <f DEBUGMSG>
248
//
249
//------------------------------------------------------------------------------
250
void WINAPIV
251
NKDbgPrintfW(
252
LPCWSTR lpszFmt,
253
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
254
)
255![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
256
va_list arglist;
257
va_start(arglist, lpszFmt);
258
NKvDbgPrintfW(lpszFmt, arglist);
259
va_end(arglist);
260
}
261![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
262
VOID NKvDbgPrintfW (LPCWSTR lpszFmt, va_list lpParms)
263![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
264
if (fSysStarted && !InSysCall ())
265
NKvDbgPrintfWOnStack (lpszFmt, lpParms);
266
else
267
_NKvDbgPrintfW(lpszFmt, lpParms);
268
}
269![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
270![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
271
//------------------------------------------------------------------------------
272
//------------------------------------------------------------------------------
273
int
274
NKwvsprintfW(
275
LPWSTR lpOut,
276
LPCWSTR lpFmt,
277
va_list lpParms,
278
int maxchars
279
)
280![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
281
int left, width, prec, size, sign, radix, upper, cch, cchLimit;
282
WCHAR prefix, fillch;
283
LPWSTR lpT;
284
LPCHAR lpC;
285![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
union
{
286
long l;
287
unsigned long ul;
288
__int64 i64;
289
WCHAR sz[sizeof(long)];
290
} val;
291![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
292
cchLimit = maxchars;
293![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
while (*lpFmt)
{
294![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (*lpFmt==(WCHAR)'%')
{
295![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* read the flags. These can be in any order */
296
left=0;
297
prefix=0;
298![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
while (*++lpFmt)
{
299
if (*lpFmt==(WCHAR)'-')
300
left++;
301
else if (*lpFmt==(WCHAR)'#')
302
prefix++;
303
else
304
break;
305
}
306![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* find fill character */
307![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (*lpFmt==(WCHAR)'0')
{
308
fillch=(WCHAR)'0';
309
lpFmt++;
310
} else
311
fillch=(WCHAR)' ';
312![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* read the width specification */
313
lpFmt=SP_GetFmtValue(lpFmt,&cch, &lpParms);
314
width=cch;
315![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* read the precision */
316![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (*lpFmt==(WCHAR)'.')
{
317
lpFmt=SP_GetFmtValue(++lpFmt,&cch, &lpParms);
318
prec=cch;
319
} else
320
prec=-1;
321![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* get the operand size */
322
size=1;
323![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (*lpFmt=='l')
{
324
lpFmt++;
325![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
} else if (*lpFmt=='h')
{
326
size=0;
327
lpFmt++;
328![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
} else if ((*lpFmt == 'I') && (*(lpFmt+1) == '6') && (*(lpFmt+2) == '4'))
{
329
lpFmt+=3;
330
size = 2;
331
}
332
upper=0;
333
sign=0;
334
radix=10;
335![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
switch (*lpFmt)
{
336
case 0:
337
goto errorout;
338
case (WCHAR)'i':
339
case (WCHAR)'d':
340
sign++;
341
case (WCHAR)'u':
342![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* turn off prefix if decimal */
343
prefix=0;
344
donumeric:
345![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* special cases to act like MSC v5.10 */
346
if (left || prec>=0)
347
fillch=(WCHAR)' ';
348
if (size == 1)
349
val.l=va_arg(lpParms, long);
350
else if (size == 2)
351
val.i64 = va_arg(lpParms, __int64);
352
else if (sign)
353
val.l=va_arg(lpParms, short);
354
else
355
val.ul=va_arg(lpParms, unsigned);
356
if (sign && val.l<0L)
357
val.l=-val.l;
358
else
359
sign=0;
360
lpT=lpOut;
361![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* blast the number backwards into the user buffer */
362
if (size == 2)
363
cch=SP_PutNumber64(lpOut,val.i64,cchLimit,radix,upper);
364
else
365
cch=SP_PutNumber(lpOut,val.l,cchLimit,radix,upper);
366
if (!(cchLimit-=cch))
367
goto errorout;
368
lpOut+=cch;
369
width-=cch;
370
prec-=cch;
371
if (prec>0)
372
width-=prec;
373![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* fill to the field precision */
374
while (prec-->0)
375
out((WCHAR)'0');
376![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (width>0 && !left)
{
377![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* if we're filling with spaces, put sign first */
378![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (fillch!=(WCHAR)'0')
{
379![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (sign)
{
380
sign=0;
381
out((WCHAR)'-');
382
width--;
383
}
384![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (prefix)
{
385
out(prefix);
386
out((WCHAR)'0');
387
prefix=0;
388
}
389
}
390
if (sign)
391
width--;
392![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* fill to the field width */
393
while (width-->0)
394
out(fillch);
395![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* still have a sign? */
396
if (sign)
397
out((WCHAR)'-');
398![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (prefix)
{
399
out(prefix);
400
out((WCHAR)'0');
401
}
402![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* now reverse the string in place */
403
SP_Reverse(lpT,lpOut-1);
404![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
} else
{
405![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* add the sign character */
406![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (sign)
{
407
out((WCHAR)'-');
408
width--;
409
}
410![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (prefix)
{
411
out(prefix);
412
out((WCHAR)'0');
413
}
414![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* reverse the string in place */
415
SP_Reverse(lpT,lpOut-1);
416![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* pad to the right of the string in case left aligned */
417
while (width-->0)
418
out(fillch);
419
}
420
break;
421
case (WCHAR) 'p' :
422
// Fall into case below, since NT is going to 64 bit
423
// they are starting to use p to indicate a pointer
424
// value. They only seem to support lower case 'p'
425
case (WCHAR)'X':
426
upper++;
427
case (WCHAR)'x':
428
radix=16;
429
if (prefix)
430
if (upper)
431
prefix=(WCHAR)'X';
432
else
433
prefix=(WCHAR)'x';
434
goto donumeric;
435
case (WCHAR)'c':
436
val.sz[0] = va_arg(lpParms, WCHAR);
437
val.sz[1]=0;
438
lpT=val.sz;
439
cch = 1; // Length is one character.
440![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* stack aligned to larger size */
441
goto putstring;
442
case 'a': // ascii string!
443
case 'S':
444
PrtAscii:
445
if (!(lpC=va_arg(lpParms, LPCHAR)))
446
lpC = "(NULL)";
447
cch=strlen(lpC);
448
if (prec>=0 && cch>prec)
449
cch=prec;
450
width -= cch;
451![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (left)
{
452
while (cch--)
453
out((WCHAR)*lpC++);
454
while (width-->0)
455
out(fillch);
456![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
} else
{
457
while (width-->0)
458
out(fillch);
459
while (cch--)
460
out((WCHAR)*lpC++);
461
}
462
break;
463
case 's':
464
if (!size)
465
goto PrtAscii;
466
if (!(lpT=va_arg(lpParms,LPWSTR)))
467
lpT = L"(NULL)";
468
cch=strlenW(lpT);
469
putstring:
470
if (prec>=0 && cch>prec)
471
cch=prec;
472
width -= cch;
473![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (left)
{
474
while (cch--)
475
out(*lpT++);
476
while (width-->0)
477
out(fillch);
478![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
} else
{
479
while (width-->0)
480
out(fillch);
481
while (cch--)
482
out(*lpT++);
483
}
484
break;
485
default:
486![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
out(*lpFmt); /**//* Output the invalid char and continue */
487
break;
488
}
489![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
} else /**//* character not a '%', just do it */
490
out(*lpFmt);
491![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* advance to next format string character */
492
lpFmt++;
493
}
494
errorout:
495
*lpOut=0;
496
return maxchars-cchLimit;
497
}
498![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
499![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
500![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
501
//------------------------------------------------------------------------------
502
// GetFmtValue
503
// reads a width or precision value from the format string
504
//------------------------------------------------------------------------------
505
LPCWSTR
506
SP_GetFmtValue(
507
LPCWSTR lpch,
508
int *lpw,
509
va_list *plpParms
510
)
511![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
512
int i=0;
513![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
if (*lpch == TEXT('*'))
{
514
*lpw = va_arg(*plpParms, int);
515
lpch++;
516![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
} else
{
517![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
while (*lpch>=(WCHAR)'0' && *lpch<=(WCHAR)'9')
{
518
i = i*10 + (*lpch-(WCHAR)'0');
519
lpch++;
520
}
521
*lpw=i;
522
}
523![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//* return the address of the first non-digit character */
524
return lpch;
525
}
526![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
527![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
528![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
529
//------------------------------------------------------------------------------
530
//------------------------------------------------------------------------------
531
void
532
SP_Reverse(
533
LPWSTR lpFirst,
534
LPWSTR lpLast
535
)
536![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
537
int swaps;
538
WCHAR tmp;
539
swaps = ((((DWORD)lpLast - (DWORD)lpFirst)/sizeof(WCHAR)) + 1)/2;
540![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
while (swaps--)
{
541
tmp = *lpFirst;
542
*lpFirst++ = *lpLast;
543
*lpLast-- = tmp;
544
}
545
}
546![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
547
const WCHAR lowerval[] = TEXT("0123456789abcdef");
548
const WCHAR upperval[] = TEXT("0123456789ABCDEF");
549![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
550![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
551![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
552
//------------------------------------------------------------------------------
553
//------------------------------------------------------------------------------
554
int
555
SP_PutNumber(
556
LPWSTR lpb,
557
ULONG n,
558
int limit,
559
int radix,
560
int mycase
561
)
562![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
563
int used = 0;
564![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
while (limit--)
{
565
*lpb++ = (mycase ? upperval[(n % radix)] : lowerval[(n % radix)]);
566
used++;
567
if (!(n /= radix))
568
break;
569
}
570
return used;
571
}
572![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
573![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
574![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
575
//------------------------------------------------------------------------------
576
//------------------------------------------------------------------------------
577
int
578
SP_PutNumber64(
579
LPWSTR lpb,
580
__int64 i64,
581
int limit,
582
int radix,
583
int mycase
584
)
585![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
586
int used = 0;
587![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
while (limit--)
{
588
*lpb++ = (mycase ? upperval[(i64 % radix)] : lowerval[(i64 % radix)]);
589
used++;
590
if (!(i64 /= radix))
591
break;
592
}
593
return used;
594
}
595![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
596