PDF文件内容出现重叠现象解析

背景:

针对开发过程中出现管理员权限生成PDF文件不会出现重叠现象,但是普通权限下生成PDF文件不会出现重叠现象分析:

方案1:

升级管理员权限

cpp 复制代码
bool createProcessWithAdmin(const wchar_t* process_name, LPPROCESS_INFORMATION process)
{
    HANDLE hToken = NULL;
    HANDLE hTokenDup = NULL;

    // 检查进程名称是否为空
    if (process_name == NULL || wcslen(process_name) == 0) {
        debug3("Failed to process_name");
        return false;
    }

    // 获取当前进程的访问令牌,具有所有权限
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
    {
        debug3("OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)");
        return false;
    }

    // 复制进程令牌,设置为主要令牌,供新进程使用
    if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenPrimary, &hTokenDup))
    {
        debug3("DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenPrimary, &hTokenDup)");
        CloseHandle(hToken);
        return false;
    }

    // 定义启动信息结构体
    STARTUPINFO si;
    LPVOID pEnv = NULL;
    DWORD dwSessionId = WTSGetActiveConsoleSessionId();

    // 初始化 STARTUPINFO 结构体
    ZeroMemory(&si, sizeof(STARTUPINFO));

    // 设置令牌信息
    if (!SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD)))
    {
        debug3("SetTokenInformation");
        CloseHandle(hToken);
        CloseHandle(hTokenDup);
        return false;
    }

    // 设置启动信息
    si.cb = sizeof(STARTUPINFO);
    si.lpDesktop = L"WinSta0\\Default";
    si.wShowWindow = SW_SHOW;
    si.dwFlags = STARTF_USESHOWWINDOW;

    // 创建环境块
    if (!CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE))
    {
        debug3("CreateEnvironmentBlock");
        CloseHandle(hToken);
        CloseHandle(hTokenDup);
        return false;
    }

    // 使用复制的令牌创建具有管理员权限的新进程
    if (!CreateProcessAsUser(hTokenDup, process_name, NULL, NULL, NULL, FALSE,
        NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
        pEnv, NULL, &si, process))
    {
        debug3("CreateProcessAsUser");
        CloseHandle(hToken);
        CloseHandle(hTokenDup);
        return false;
    }

    // 销毁环境块
    if (pEnv)
    {
        DestroyEnvironmentBlock(pEnv);
    }

    // 关闭令牌句柄
    CloseHandle(hToken);
    CloseHandle(hTokenDup);

    return true;
}

test模块:

cpp 复制代码
//方法1:
void test()
{
            SHELLEXECUTEINFOW shExInfo = { 0 };  // 初始化 `SHELLEXECUTEINFOW` 结构
            shExInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
            shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;   // 创建进程并返回进程句柄
            shExInfo.lpVerb = L"runas";                 // 使用管理员权限运行
            shExInfo.lpFile = t;                        // 要运行的程序路径
            shExInfo.lpParameters = NULL;               // 命令行参数
            shExInfo.lpDirectory = NULL;                // 初始目录
            shExInfo.nShow = SW_SHOWNORMAL;             // 设置窗口显示模式

            // 调用 ShellExecuteExW 以管理员权限运行程序
            b = ShellExecuteExW(&shExInfo);
            //方法2:已知管理员用户和管理员密码实现权限升级:CreateProcessWithLogonW
            STARTUPINFOW si = { 0 };
            PROCESS_INFORMATION pi = { 0 };
            wchar_t cmdLine[MAX_PATH * 2];
            wchar_t userName[] = L"SHhao";
            wchar_t domain[] = L"";
            wchar_t password[] = L"812617";

            // 构建命令行
            if (swprintf_s(cmdLine, MAX_PATH * 2, L"\"%s\" %s", cmd, t) < 0) {
                wprintf(L"Failed to construct command line.\n");
                return -1;
            }

            // 初始化 STARTUPINFOW
            si.cb = sizeof(STARTUPINFOW);
            si.dwFlags = STARTF_USESHOWWINDOW;
            si.wShowWindow = SW_SHOWNORMAL;

            // 调用 CreateProcessWithLogonW
            BOOL b = CreateProcessWithLogonW(
                userName,                     // 用户名
                domain,                       // 域(为空表示本地)
                password,                     // 密码
                LOGON_WITH_PROFILE,           // 使用用户配置文件
                NULL,                         // 应用程序路径(NULL 表示从命令行获取)
                cmdLine,                      // 完整命令行
                CREATE_NEW_CONSOLE,           // 创建新控制台
                NULL,                         // 环境变量(NULL 表示使用父进程环境)
                NULL,                         // 工作目录
                &si,                          // 启动信息
                &pi                           // 进程信息
                );
            debug3("spawning %ls as administrator - 1", t);

            //方法3:利用令牌实现管理员权限升级
            PROCESS_INFORMATION pi = { 0 };
            b = createProcessWithAdmin(t, &pi);
 }

方法2:

原因:

熟悉LitePDF模块代码,最终发现由于从EMF文件中回放生成PDF时,需要利用DC来计算PDF中文本区域,而代码处理时创建了屏幕DC来计算文本区域,导致文本绘制区域计算错误,因此出现文本重叠到一起的问题

修改点:

回放时根据外部传入的参数创建设备上下文来处理文本区域

最终采用方法2解决

相关推荐
HellowAmy6 小时前
我的C++规范 - 玩一个小游戏
开发语言·c++·代码规范
自学不成才6 小时前
深度复盘:一次flutter应用基于内存取证的黑盒加密破解实录并完善算法推理助手
c++·python·算法·数据挖掘
玖釉-8 小时前
[Vulkan 学习之路] 08 - 给图片穿马甲:图像视图 (Image Views)
c++·windows·图形渲染
m0_748250038 小时前
C++ 信号处理
c++·算法·信号处理
yuyanjingtao9 小时前
动态规划 背包 之 凑钱
c++·算法·青少年编程·动态规划·gesp·csp-j/s
scx2013100410 小时前
20260112树状数组总结
数据结构·c++·算法·树状数组
星竹晨L10 小时前
【C++内存安全管理】智能指针的使用和原理
开发语言·c++
智者知已应修善业10 小时前
【C语言 dfs算法 十四届蓝桥杯 D飞机降落问题】2024-4-12
c语言·c++·经验分享·笔记·算法·蓝桥杯·深度优先
玖釉-10 小时前
[Vulkan 学习之路] 09 - 显卡的流水线工厂:图形管线概览 (Graphics Pipeline)
c++·windows·图形渲染
无限进步_11 小时前
【C语言&数据结构】二叉树遍历:从前序构建到中序输出
c语言·开发语言·数据结构·c++·算法·github·visual studio