拦截cncapi.dll中CncRunSingleLine调用后程序崩溃问题求助
问题描述
我正在修改名为EdingCNC的应用程序,该程序依赖动态链接库cncapi.dll实现核心功能。我的目标是拦截该DLL中的CncRunSingleLine函数调用,必要时修改行为后转发至原函数,其余函数通过#pragma comment(linker, "/export:...=...,@...")直接转发。
该函数在cncapi.dll中的签名为:
CNC_RC EXP2DF __stdcall CncRunSingleLine(char *text);
实现方案(代理DLL)
为拦截该函数,我创建了一个同名导出的代理DLL,捕获CncRunSingleLine的调用,执行额外逻辑后调用原cncapi.dll中的函数。当前实现代码如下:
#define WIN32_LEAN_AND_MEAN #include <windows.h> #include <iostream> // HINSTANCE gDllhInstance = NULL; // 当前DLL句柄的全局存储 BOOL ProcessAttach(); BOOL ProcessDetach(); BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, PVOID pvReserved) { UNREFERENCED_PARAMETER(pvReserved); switch (dwReason) { case DLL_PROCESS_ATTACH: gDllhInstance = hInstDLL; return ProcessAttach(); case DLL_PROCESS_DETACH: return ProcessDetach(); } return TRUE; } BOOL ProcessAttach() { return TRUE; } BOOL ProcessDetach() { return TRUE; } // 定义原函数的函数指针类型 typedef enum CNC_RC { CNC_RC_OK = 0, /* 成功 */ CNC_RC_BUF_EMPTY = 1, /* 缓冲区为空 */ CNC_RC_TRACE = 2, /* 跟踪信息 */ CNC_RC_USER_INFO = 3, /* 用户消息 */ CNC_RC_SHUTDOWN = 4, /* CMD_CLOSE后处理请求返回 */ CNC_RC_EXISTING = 5, /* 共享内存已存在 */ CNC_RC_ALREADY_RUNS = 6, /* 服务端已在运行 */ CNC_RC_ALREADY_CONNECTED = 7, /* 已调用CncConnectServer() */ CNC_RC_ERR = -1, /* 无数据在FIFO中 */ CNC_RC_ERR_PAR = -2, /* 参数或参数值错误,详见文本 */ CNC_RC_ERR_STATE = -3, /* 状态错误,操作不允许,详见文本 */ CNC_RC_ERR_CONFIG = -4, /* 配置错误,例如轴不存在 */ CNC_RC_ERR_INT = -5, /* 解释器错误,详见解释器错误状态 */ CNC_RC_ERR_CE = -6, /* 命令包错误 */ CNC_RC_ERR_EXE = -7, /* 执行错误 */ CNC_RC_ERR_CPU = -8, /* CPU错误,详见子代码、文本,需重启 */ CNC_RC_ERR_MOT = -9, /* 轨迹生成器错误,详见子代码、文本 */ CNC_RC_ERR_SYS = -10, /* 服务端系统错误,详见文本 */ CNC_RC_ERR_TIMEOUT = -11, /* 通用超时错误 */ CNC_RC_EXE_CE = -12, /* 执行命令包错误 */ CNC_RC_ERR_FILEOPEN = -13, /* 文件打开错误 */ CNC_RC_ERR_COLLISION = -14, /* 碰撞 */ CNC_RC_ERR_SERVER_NOT_RUNNING = -15,/* 尝试以监控模式连接,但服务端未运行 */ CNC_RC_ERR_VERSION_MISMATCH = -16, /* 服务端与CNCAPI版本不匹配 */ CNC_RC_ERR_NOT_CONNECTED = -17 /* CNCAPI未调用CncConnectServer */ } CNC_RC; #define C_DLL_EXPORT __declspec(dllexport) // 或自定义宏 typedef CNC_RC(__stdcall* pfCncRunSingleLine)(char* text); // 正确的函数指针类型 extern "C" { // 确保C风格链接(无名称修饰) // 导出函数,返回类型正确(CNC_RC) C_DLL_EXPORT CNC_RC CncRunSingleLine(char* text) { if (text == nullptr) { ::MessageBoxW(NULL, L"无效输入参数:text为NULL", L"错误", MB_ICONERROR); return CNC_RC_ERR; // 参数无效时返回错误 } // 1) 获取原DLL句柄(根据需要调整DLL名称) HMODULE hModule = ::GetModuleHandle(TEXT("_cncapi.dll")); // 必要时调整DLL名称 if (!hModule) { // 未找到原CNC API DLL时显示错误并返回失败码 ::MessageBoxW(NULL, L"加载原CNC API DLL失败", L"错误", MB_ICONERROR); return CNC_RC_ERR; // 返回错误码 } // 2) 获取原DLL中的函数地址 pfCncRunSingleLine pOriginalCncRunSingleLine = (pfCncRunSingleLine)::GetProcAddress(hModule, "CncRunSingleLine"); if (!pOriginalCncRunSingleLine) { // 未找到CncRunSingleLine函数时显示错误并返回失败码 ::MessageBoxW(NULL, L"未找到CncRunSingleLine函数", L"错误", MB_ICONERROR); return CNC_RC_ERR; // 返回错误码 } // 3) 调用原函数并返回结果 CNC_RC result = pOriginalCncRunSingleLine(text); // 调用函数 // 检查结果是否有效 if (result != CNC_RC_OK) // 必要时替换为正确的成功返回码 { ::MessageBoxW(NULL, L"CncRunSingleLine函数调用失败", L"错误", MB_ICONERROR); } return result; // 返回原函数的结果 } }
问题详情
- 拦截函数已被成功调用,执行结果符合预期
- 函数执行完成后程序立即崩溃
- 崩溃发生在
CncRunSingleLine返回之后,尽管功能已正常实现
已尝试的排查步骤
- 确认拦截函数被调用且结果符合预期
- 检查返回值,确认
CncRunSingleLine在崩溃前已执行完成 - 验证
hModule正确获取到_cncapi.dll,函数指针有效 - 通过
MessageBoxW确认崩溃发生在CncRunSingleLine返回之后
内容的提问来源于stack exchange,提问作者Felix Prackwieser
相关产品推荐
相关产品推荐

