• Wine debug笔记


    wine基础知识可参见:
    https://www.cnblogs.com/chendeqiang/p/14309515.html
    https://wiki.winehq.org/Main_Page

    替换OpenFileDialog对话框

    这是我的第一个课题,尽管失败了,仍然值得纪念。

    目的:使用系统调用对话框代替Wine原生的windows对话框。
    工具:vscode,shell,ubuntu20.04,windows
    前期准备:windows 窗口调用学习,了解创建窗口,消息传递等基本知识。
    wine原生对话框
    对标对话框
    历时:7天。

    首先想到的是替换explore风格,来整体替换对话框风格,但是没有找到可替换或更改的地方。
    在追踪过程中,调研到了打开文件对话框函数,通过阅读msdn文档,对打开/保存文件对话框函数和概念有了一些了解。

    由于这是第一次使用Windows API,因此大多数时间都花在了查阅和使用windows api上。

    接下来想到自己做一个gtk的二进制,然后通过调用gtk二进制来取代windows api的调用。

    首先是学习gtk窗口基本知识

    然后制作了一个对话框窗口demo

    接下来是替换wine源码中打开文件对话框的调用。
    定位函数:DialogOpenFile:

    static void DialogOpenFile(void)
    {
        //文件样式控制
        OPENFILENAMEW ofn;
    
        WCHAR wszFile[MAX_PATH] = {''};
        static const WCHAR wszDefExt[] = {'r','t','f',''};
    
        ZeroMemory(&ofn, sizeof(ofn));
    
        ofn.lStructSize = sizeof(ofn);
        ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ENABLESIZING;
        ofn.hwndOwner = hMainWnd;
        ofn.lpstrFilter = wszFilter;
        ofn.lpstrFile = wszFile;
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrDefExt = wszDefExt;
        ofn.nFilterIndex = fileformat_number(fileFormat)+1;
    
        if(GetOpenFileNameW(&ofn))
        {
            if(prompt_save_changes())
                //很明显此处传入 ofn.lpstrFile 作为文件名,然后执行了打开文件对话框,因此我的想法是该写GetOpenFileNameW函数
                DoOpenFile(ofn.lpstrFile);
        }
    }
    

    查看GetOpenFileNameW函数:

    BOOL WINAPI GetOpenFileNameW(OPENFILENAMEW *ofn)
    {
        TRACE("flags 0x%08x
    ", ofn->Flags);
    
        if (!valid_struct_size( ofn->lStructSize ))
        {
            COMDLG32_SetCommDlgExtendedError( CDERR_STRUCTSIZE );
            return FALSE;
        }
    
        /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
        if (ofn->Flags & OFN_FILEMUSTEXIST)
            ofn->Flags |= OFN_PATHMUSTEXIST;
    
        if (is_win16_looks(ofn->Flags))
            return GetFileName31W(ofn, OPEN_DIALOG);
        else
        {
            FileOpenDlgInfos info;
    
            init_filedlg_infoW(ofn, &info);
            return GetFileDialog95(&info, OPEN_DIALOG);
        }
    }
    

    我的想法很简单,先测试一个demo,把GetOpenFileNameW中的代码都屏蔽,然后使用system调用:

    BOOL WINAPI GetOpenFileNameW(OPENFILENAMEW *ofn)
    {
    //cdq
    #if 1
        system("~/myOpenFileDialog.out");
    #else
        TRACE("flags 0x%08x
    ", ofn->Flags);
    
        if (!valid_struct_size( ofn->lStructSize ))
        {
            COMDLG32_SetCommDlgExtendedError( CDERR_STRUCTSIZE );
            return FALSE;
        }
    
        /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
        if (ofn->Flags & OFN_FILEMUSTEXIST)
            ofn->Flags |= OFN_PATHMUSTEXIST;
    
        if (is_win16_looks(ofn->Flags))
            return GetFileName31W(ofn, OPEN_DIALOG);
        else
        {
            FileOpenDlgInfos info;
    
            init_filedlg_infoW(ofn, &info);
            return GetFileDialog95(&info, OPEN_DIALOG);
        }
    
    }
    #endif
    

    接下来就是灾难了,
    这个文件名我不会传回来,

    大体上我想了两种方案,一种是将gtk编入wine,另一种是进程间通信。

    如果将gtk编入wine,就需要在wine工程中引入gtk 代码,整个makefile也需要重新改写,我尝试了一段时间后,觉得代价太大了,会破坏wine工程,就放弃了。

    第二种方案是我制作一个可执行程序,应用进程间通信的方式传入文件名。

    进程间通信我先后用了管道,公共文件读写,共享内存等方式,
    最后总是父进程总是不等待子进程结束就继续执行了,即没等文件名返回父进程就已经执行打开文件的操作了。

    经过一系列的调研,发现wine中混用了windows和linux的进程和线程,最后通过wineserve统一管理进程间通信问题,
    但是没有找到wineserve的使用方法,而且进程间通信的问题入门有点难了,就放弃了这个课题。

    Foxmail无法发送邮件

    目的:解决Foxmail无法发送邮件的问题。
    现象:
    1.在收件人地址栏写入收件人后,如果加上分号,无法显示收件人
    2.点击发送后邮件发送失败
    3.在草稿箱可以看到邮件人地址除了正常收件人地址外还多了一个“?”
    历时:10天
    工具:QtCreater,KylinV10Pro

    首先是复现bug:
    这个bug是在crossover上出现的,
    但是我用wine运行foxmail时和crossover的表现不一样:
    crossover表现

    那么wine为什么会和crossover表现的不一样,是因为crossover单独维护了一个wine版本吗?

    经过一系列调查,我发现问题可能在于wine缺少html渲染,导致所有html都无法显示,

    我新建了一个wine容器,发现果然wine内置了html引擎,

    接下来我拷贝了这个crossover新建的容器,并命名为~/.wine

    然后再启动Foxmail,

    果然发现wine和crossover表现一致了,因此这个bug也可以复现了。

    然后是问题识别:
    一开始结论是收件人地址栏不显示收件人导致数据发不出去。

    后续调查发现,收件人不显示不影响邮件发送,
    那么这个bug就不是一个bug而是两个bug:
    1.收件人不显示
    2.邮件发不出去

    先解决邮件发不出去的问题。
    从发送失败后的草稿箱来看,收件人地址多了一个“?”

    为了复现这个现象,我模拟了一个错误地址发送,发现触发了同样的错误提示,但是一些无效字符会被Foxmail处理掉。

    所以现在肯定,就是这个多出来的“?”导致邮件发不出去,

    那么多出来的是什么呢?

    我的第一直觉多出来的是‘ ’转义字符;因为windows的换行符是‘ ’,Linux的换行符是' ',所以肯定是' '在linux下无法被识别,且被当成了有效字符,所以变成了“?”,导致邮件发不出去。

  • 相关阅读:
    加载默认图片,如何避免img标签陷入onerror事件死循环
    Windows 7安装解压版MySQL 5.6(不包含配置文件优化)
    【总结2】PhpStorm利用XDebug调试PHP技巧
    【总结1】PhpStorm配置XDebug(远程)调试PHP
    JavaScript跳转到页面某个锚点#
    数据库查询中的特殊字符的问题
    CSS3/jQuery自己定义弹出窗体
    4.Maven概念模型,maven的生命周期,Maven坐标,依赖管理(依赖范围,依赖声明),仓库管理,私服概念
    从Wolframserver获取DC comics卡通人物数据
    S5PV210开发系列四_uCGUI的移植
  • 原文地址:https://www.cnblogs.com/chendeqiang/p/14515577.html
Copyright © 2020-2023  润新知