OutputDebugString函数分析
第一部分:位置base/win32/client/debug.c
F:\srv03rtm\base\win32/client/debug.c:379:OutputDebugStringW(
F:\srv03rtm\base\win32/client/debug.c:387: UNICODE thunk to OutputDebugStringA
F:\srv03rtm\base\win32/client/debug.c:401: OutputDebugStringA (AnsiString.Buffer);
F:\srv03rtm\base\win32/client/debug.c:543:OutputDebugStringA(
F:\srv03rtm\base\win32/client/debug.c:688: DbgPrint("\nOutputDebugString faulted during output\n");
第二部分:输出到vc调试器或者内核调试器windbg
VOID
APIENTRY
OutputDebugStringA(
IN LPCSTR lpOutputString
)
/*++
Routine Description:
This function allows an application to send a string to its debugger
for display. If the application is not being debugged, but the
system debugger is active, the system debugger displays the string.
Otherwise, this function has no effect.
此函数允许应用程序将字符串发送到其调试器
用于显示。
如果应用程序未被调试,但
系统调试器处于活动状态,系统调试器将显示字符串。
否则,此功能无效。
Arguments:
lpOutputString - Supplies the address of the debug string to be sent
to the debugger.
Return Value:
None.
--*/
{
ULONG_PTR ExceptionArguments[2];
DWORD WaitStatus;
//提出一个例外。如果正在调试APP,调试器
会抓住并处理这件事。否则,内核调试器将被调用。
// Raise an exception. If APP is being debugged, the debugger
// will catch and handle this. Otherwise, kernel debugger is
// called.
//
try {
ExceptionArguments[0] = strlen (lpOutputString)+1;
ExceptionArguments[1] = (ULONG_PTR)lpOutputString;
RaiseException (DBG_PRINTEXCEPTION_C,0,2,ExceptionArguments);
} except (EXCEPTION_EXECUTE_HANDLER) {
//我们捕获了调试异常,因此没有用户模式
调试器。
//如果有DBWIN正在运行,请发送字符串
如果没有,请使用DbgPrint将其发送到内核
调试器。
//DbgPrint一次只能处理511个字符
时间,所以用力喂它。
// We caught the debug exception, so there's no user-mode
// debugger. If there is a DBWIN running, send the string
// to it. If not, use DbgPrint to send it to the kernel
// debugger. DbgPrint can only handle 511 characters at a
// time, so force-feed it.
//
char szBuf[512];
size_t cchRemaining;
LPCSTR pszRemainingOutput;
DWORD OldError;
HANDLE SharedFile = NULL;
LPSTR SharedMem = NULL;
HANDLE AckEvent = NULL;
HANDLE ReadyEvent = NULL;
static HANDLE DBWinMutex = NULL;
static BOOLEAN CantGetMutex = FALSE;
OldError = GetLastError ();
//
// look for DBWIN.
//
if (!DBWinMutex && !CantGetMutex) {
HANDLE MutexHandle;
MutexHandle = CreateDBWinMutex();
if (MutexHandle == NULL) {
CantGetMutex = TRUE;
} else {
if (InterlockedCompareExchangePointer (&DBWinMutex, MutexHandle, NULL) != NULL) {
CloseHandle (MutexHandle);
}
}
}
if (DBWinMutex) {
WaitStatus = WaitForSingleObject(DBWinMutex, DBWIN_TIMEOUT);
if (WaitStatus == WAIT_OBJECT_0 || WaitStatus == WAIT_ABANDONED) {
SharedFile = OpenFileMapping(FILE_MAP_WRITE, FALSE, "DBWIN_BUFFER");
if (SharedFile) {
SharedMem = MapViewOfFile (SharedFile,
FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 0);
if (SharedMem) {
AckEvent = OpenEvent(SYNCHRONIZE, FALSE,
"DBWIN_BUFFER_READY");
if (AckEvent) {
ReadyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE,
"DBWIN_DATA_READY");
}
}
}
if (!ReadyEvent) {
ReleaseMutex(DBWinMutex);
}
}
}
try {
pszRemainingOutput = lpOutputString;
cchRemaining = strlen(pszRemainingOutput);
while (cchRemaining > 0) {
int used;
if (ReadyEvent && WaitForSingleObject(AckEvent, DBWIN_TIMEOUT)
== WAIT_OBJECT_0) {
*((DWORD *)SharedMem) = GetCurrentProcessId();
used = (int)((cchRemaining < 4095 - sizeof(DWORD)) ?
cchRemaining : (4095 - sizeof(DWORD)));
RtlCopyMemory(SharedMem+sizeof(DWORD),
pszRemainingOutput,
used);
SharedMem[used+sizeof(DWORD)] = 0;
SetEvent(ReadyEvent);
} else {
used = (int)((cchRemaining < sizeof(szBuf) - 1) ?
cchRemaining : (int)(sizeof(szBuf) - 1));
RtlCopyMemory(szBuf, pszRemainingOutput, used);
szBuf[used] = 0;
DbgPrint("%s", szBuf);
}
pszRemainingOutput += used;
cchRemaining -= used;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
DbgPrint("\nOutputDebugString faulted during output\n");
}
if (AckEvent) {
CloseHandle(AckEvent);
}
if (SharedMem) {
UnmapViewOfFile(SharedMem);
}
if (SharedFile) {
CloseHandle(SharedFile);
}
if (ReadyEvent) {
CloseHandle(ReadyEvent);
ReleaseMutex(DBWinMutex);
}
SetLastError (OldError);
}
}