Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OutputDebugString() in console

I am using a third party library that uses the function OutputDebugString(), and when reading the MSDN documentation it seems to indicate that this is for printing to the debugger.

But that is inconvenient in my case, is there a way to read this output if there is no debugger connected?

If it was my LIB, I would prefer the output to go to stdout/stderr whenever the user passes --debug or similar, but since it's not I am looking for other ways to pass this info to the console (or file) without connecting a debugger.

like image 926
Zitrax Avatar asked Jan 04 '17 14:01

Zitrax


1 Answers

the OutputDebugStringA generate exception DBG_PRINTEXCEPTION_C (W version in win10 - DBG_PRINTEXCEPTION_WIDE_C) with 2 arguments - (string length in characters + 1, string pointer) - as result we can handle this exception yourself (system default handler for this exception do this).

example handler for redirect OutputDebugString to console:

LONG NTAPI VexHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
    PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;

    switch (ExceptionRecord->ExceptionCode)
    {
    case DBG_PRINTEXCEPTION_WIDE_C:
    case DBG_PRINTEXCEPTION_C:

        if (ExceptionRecord->NumberParameters >= 2)
        {
            ULONG len = (ULONG)ExceptionRecord->ExceptionInformation[0];

            union {
                ULONG_PTR up;
                PCWSTR pwz;
                PCSTR psz;
            };

            up = ExceptionRecord->ExceptionInformation[1];

            HANDLE hOut = GetStdHandle(STD_ERROR_HANDLE);

            if (ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C)
            {
                // localized text will be incorrect displayed, if used not CP_OEMCP encoding 
                // WriteConsoleA(hOut, psz, len, &len, 0);

                // assume CP_ACP encoding
                if (ULONG n = MultiByteToWideChar(CP_ACP, 0, psz, len, 0, 0))
                {
                    PWSTR wz = (PWSTR)alloca(n * sizeof(WCHAR));

                    if (len = MultiByteToWideChar(CP_ACP, 0, psz, len, wz, n))
                    {
                        pwz = wz;
                    }
                }
            }

            if (len)
            {
                WriteConsoleW(hOut, pwz, len - 1, &len, 0);
            }

        }
        return EXCEPTION_CONTINUE_EXECUTION;
    }

    return EXCEPTION_CONTINUE_SEARCH;
}

and for set this handler need call:

AddVectoredExceptionHandler(TRUE, VexHandler);

the system implementation of OutputDebugString like here - it really called RaiseException with exactly this arguments, only in exception handler instead MessageBox - code described here.

like image 167
RbMm Avatar answered Sep 23 '22 01:09

RbMm