OutputDebugString函数分析

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);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/439353.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows下安装rabbitMQ并开通管理界面和允许远程访问

如题&#xff0c;在windows下安装一个rabbitMQ server&#xff1b;然后用浏览器访问其管理界面&#xff1b;由于rabbitMQ的默认账号guest默认只能本机访问&#xff0c;因此需要设置允许其他机器远程访问。这跟mysql的思路很像&#xff0c;默认只能本地访问&#xff0c;要远程访…

Oracle架构之表空间详解

文章目录 1 表空间介绍1.1 简介1.2 表空间分类1.2.1 SYSTEM 表空间1.2.2 SYSAUX 表空间1.2.3 UNDO 表空间1.2.4 USERS 表空间 1.3 表空间字典与本地管理1.3.1 字典管理表空间&#xff08;Dictionary Management Tablespace&#xff0c;DMT&#xff09;1.3.2 本地管理方式的表空…

计算机网络(十) —— IP协议详解,理解运营商和全球网络

目录 一&#xff0c;关于IP 1.1 什么是IP协议 1.2 前置认识 二&#xff0c;IP报头字段详解 三&#xff0c;网段划分 3.1 IP地址的构成 3.2 网段划分 3.3 子网划分 3.4 IP地址不足问题 四&#xff0c;公网IP和私有IP 五&#xff0c;理解运营商和全球网络 六&#xff…

基于大数据技术的颈椎病预防交流与数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

【优选算法】(第二十一篇)

目录 外观数列(medium) 题目解析 讲解算法原理 编写代码 数⻘蛙&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 外观数列(medium) 题目解析 1.题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 2.题目描述 给定⼀个正整数n&#xff0…

算法篇1:双指针思想的运用(1)--C++

一.算法解析 双指针&#xff0c;顾名思义就是两个指针&#xff0c;常见的算法中&#xff0c;我们可以看到两种&#xff1a; 1.对撞指针&#xff1a;一般用于顺序结构&#xff0c;也称为左右指针。 对撞指针从两端向中间移动。一个指针从最左端开始&#xff0c;另一个从最右端…

Yolov8轻量级网络改进GhostNet

1,理论部分 由于内存和计算资源有限,在移动设备上部署卷积神经网络 (CNN) 很困难。我们的目标是通过利用特征图中的冗余,为 CPU 和 GPU 等异构设备设计高效的神经网络,这在神经架构设计中很少被研究。对于类 CPU 设备,我们提出了一种新颖的 CPU 高效 Ghost (C-Ghost) …

Mysql:数据库和表增删查改基本语句

一、数据库操作 1&#xff09;、数据库创建 创建数据库本质就是创建一个目录&#xff08;ubuntu&#xff0c;创建的目录文件存放在/var/lib/mysql&#xff09;&#xff1b;后续创建表本质就是在该目录下创建文件&#xff08;不同存储引擎&#xff0c;会创建的文件数目是不同的…

PASCAL VOC 2012数据集 20类物体,这些物体包括人、动物(如猫、狗、鸟等)、交通工具(如车、船、飞机等)以及家具(如椅子、桌子、沙发等)。

VOC2012数据集是PASCAL VOC挑战赛官方使用的数据集之一&#xff0c;主要包含20类物体&#xff0c;这些物体包括人、动物&#xff08;如猫、狗、鸟等&#xff09;、交通工具&#xff08;如车、船、飞机等&#xff09;以及家具&#xff08;如椅子、桌子、沙发等&#xff09;。每个…

计算机网络:物理层 —— 物理层下的传输媒体

文章目录 传输媒体导向性媒体同轴电缆双绞线光纤光纤分类中心波长光纤规格光纤的优缺点 非导向性媒体ISM 频段无线电波微波激光红外线可见光 传输媒体 传输媒体是计算机网络设备之间的物理通路&#xff0c;也称为传输介质或传输媒介&#xff0c;并不包含在计算机网络体系结构中…

github项目——系统设计入门

今天的github趋势&#xff0c;有几个项目印象感觉很有意思&#xff0c;之后可能会用的上&#xff0c;记录一下 系统设计入门 书籍教程类项目&#xff0c;有中文文档&#xff0c;刚好需要。 https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md…

Linux之实战命令26:timeout应用实例(六十)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

postgresql|数据库|postgis编译完成后的插件迁移应该如何做(postgis插件最终章)

一、 本文的写作理由 postgis插件一般是编译安装&#xff0c;编译安装的原因是可以选择自己喜欢的版本&#xff0c;但编译的难度也是比较高的&#xff0c;因为有各种依赖&#xff0c;依赖之间还有依赖&#xff0c;非常容易形成依赖循环&#xff0c;因此&#xff0c;失败率是比…

libevent框架、带缓冲区事件bufferevent的使用

1.简介 特点 源码包安装 2.libevent框架 创建event_base 创建添加事件 循环监听事件满足 释放event_base 相关函数了解 3.常规事件event 未决与非未决 使用fifo的读写 4.带缓冲区事件bufferevent bufferevent A.服务器创建监听器 C.给读写缓冲区设置回调 D.禁用…

基于spring boot的篮球论坛系统

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…

【Unity踩坑】使用内购时获取Google Play license key

在Unity中使用了IAP&#xff08;内购&#xff09;后&#xff0c;需要设置Google Play license key。 这个key需要在Google Play Console中&#xff08;https://play.google.com/console&#xff09;&#xff0c;找到相应的应用&#xff0c;在左侧“创收设置”里可以找到license…

电脑失声,一招搞定

早已习惯了Edge浏览器的“大声朗读”功能&#xff0c;今天值班&#xff0c;值班室用的两台电脑只配有耳机&#xff0c;没有音箱&#xff0c;顿时感觉不适。 先找了一个带功放的老音箱&#xff0c;发现少了电箱到功放的音频线。 一顿搜索&#xff0c;在找到音频线的同时&#…

Linux·进程概念(下)

1. 进程优先级 优先级就是获得某种资源的先后顺序&#xff0c;因为CPU资源是有限的&#xff0c;因此各个进程之间要去争取CPU的资源。 那么针对Linux操作系统下的PCB中&#xff0c;也就是task_struct结构体中&#xff0c;使用了int类型的变量记录了每个进程的优先级属性&#x…

【Xcode Command Line Tools】安装指南

安装指令 xcode-select --install安装 完成安装 验证 $ xcode-select -p /Library/Developer/CommandLineTools

Python机器视觉:01- 利用列表和切片操作 - 做一个弧线和图片相交的mask区域

前言&#xff1a; Python的列表处理&#xff0c;在机器视觉中经常被用到&#xff0c;这里结合基本的概念机器视觉实践案例&#xff0c;成文如下&#xff1a; 本身将实现一个&#xff0c;弧线的mask填充&#xff1a;这个mask是我的一个天文项目的应用&#xff0c;目的在于将月…