去教育版戳记源码(ARX,LISP版)
去教育版戳记源码(ARX,LISP版)
highflybird
- 登录 发表评论
CAD教育版戳记有时候很讨厌,一旦图中有这个戳记,就会传染到其它图中。就是说从有戳记的图中拷贝到没戳记的,没戳记的也会带上。
而且这个戳记不太好消除。
对于2015-2018,Autodesk公司似乎已经把这个戳记移除掉了,也就是说,用这些版本的CAD打开图,看不到戳记,也不会弹出那个戳记警告框。
保存之后,图中不会再有了(这点我没有每个版本验证)。但该死的是到了2019后,这个又出现了,不知道autodesk公司在玩什么。
关于去教育版有很多方式,ARX的方式最有效。我这里提供用了ARX源码。以及附带的生成的ARX程序。
这个程序的源码 是从网上的 wdzhangsl 引申过来,特此深表感谢!
程序的原理是从数据库指针找到戳记的偏移地址,修改此处的值,便达到了消除。
因为原代码有些重复和繁琐,特此精简,并且升级到2019。经过测试,程序有效。
因为有些CAD版本我是没办法在自己机器安装,就没有一个个CAD版本进行测试其中的偏移地址。
如果有网友能测试到我程序中没有的CAD版本的值,请告诉我或者跟帖。多谢!
下面是程序的源码和已经编译好二进制文件的压缩包。欢迎各位捉虫子和提出建议。
程序的用法是:加载后,程序会自动消除戳记,也可以用手动输入命令QJYB 来消除。
如果你把此程序加载到启动组,以后每当打开有教育版的dwg后,程序会自动消除,你需要做的仅仅是保存文件而已。
对于LISp版本,更有这两项突出功能:
1、消除打开戳记文件的错误警告框。
2、全面兼容各种CAD版本。
LISP的代码如下:(需要DynamicWrapperX支持)
ARX的核心代码如下:
#include "stdafx.h"
#include "GetProcess.h"
#include "GetFunctionAddress.h"
#include "RemoveEDU.h"
byte OffsetAddress32[6][6]={
{0xa4,0x06,0xa4,0x06,0xa4,0x06},//R15
{0xd4,0x06,0xd4,0x06,0xd4,0x06},//R16
{0xdc,0x07,0x24,0x08,0x34,0x08},//R17
{0x6c,0x08,0x74,0x08,0x7c,0x08},//R18
{0x84,0x08,0x84,0x08,0x84,0x08},//R19
{0x84,0x08,0x84,0x08,0x84,0x08},//R23
};
byte OffsetAddress64[4][6]={
{0x18,0x0b,0x18,0x0b,0x18,0x0b},//R17
{0x80,0x0b,0x88,0x0b,0x90,0x0b},//R18
{0xa8,0x0b,0xb0,0x0b,0xb8,0x0b},//R19
{0xa0,0x0b,0xa0,0x0b,0xa0,0x0b},//R23
};
int RemoveEducationStamp(WNDINFO & wi)
{
if (wi.ActiveDoc==NULL)
return FALSE;
int ret = FALSE;
CAcadUtility uti=wi.ActiveDoc.get_Utility();
//获取isEMR函数的RVA地址
INT_PTR offsetAddr = 0;
LPCSTR funcName = wi.is64bit ? "?isEMR@AcDbDatabase@@QEBA_NXZ" : "?isEMR@AcDbDatabase@@QBE_NXZ";
HMODULE hDLL = LoadLibraryEx(wi.strAcDbPath,0,DONT_RESOLVE_DLL_REFERENCES);//
LPVOID pIsEMR = GetProcAddress(hDLL,funcName);
FreeLibrary(hDLL);
if (pIsEMR == NULL)
{
pIsEMR = LoadFuncBase(wi.strAcDbPath,funcName,hDLL);
}
if (pIsEMR == NULL)
{
FUNCTION_ADDRESS funcSet;
ret = getFuncAddr(wi.strAcDbPath,funcSet);
FUNCTION_ADDRESS::iterator itr = funcSet.find(funcName);
if (itr == funcSet.end())
{
uti.Prompt(_T("找不到教育版相关函数!可能需要以管理员身份运行此程序,或者CAD版本是2015-2018.\n"));
return FALSE;
}
offsetAddr = itr->second;
pIsEMR = LPVOID((INT_PTR)wi.hAcDb + offsetAddr); //操纵数据库
}
else
{
offsetAddr = (INT_PTR)pIsEMR - (INT_PTR)hDLL;
pIsEMR = LPVOID((INT_PTR)wi.hAcDb + offsetAddr); //操纵数据库
}
//以写的方式打开CAD进程
//HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, wi.dwProcessId); //权限要求太高,可能在某些机器上运行不了
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE, FALSE, wi.dwProcessId);
if (hProcess == NULL)
{
uti.Prompt(_T("无法打开CAD进程写入!\n"));
return FALSE;
}
const DWORD bWritten = 128;
byte pEAX = 0;
SIZE_T dwNumberOfBytes = 0;
CString strTemp = wi.strVersion.Mid(1,2);
int nMajorVersion = _ttoi(strTemp.GetBuffer());
if (nMajorVersion>22)
nMajorVersion-=3;
strTemp = wi.strVersion.Mid(4,1);
int nMinorVersion = _ttoi(strTemp.GetBuffer());
if (wi.is64bit)
{
byte AsmCode[15] = {0x48,0x8B,0x49,0x08,0x33,0xC0,0x89,0x81,0x00,0x00,0x00,0x00,0x3C,0x00,0xC3};
nMajorVersion = nMajorVersion-17;
AsmCode[8]=OffsetAddress64[nMajorVersion][2*nMinorVersion];
AsmCode[9]=OffsetAddress64[nMajorVersion][2*nMinorVersion+1];
ret = WriteProcessMemory(hProcess,pIsEMR,AsmCode,sizeof(AsmCode),&dwNumberOfBytes);
}
else
{
byte AsmCode[14] = {0x8B,0x49,0x04,0x33,0xC0,0x89,0x81,0x00,0x00,0x00,0x00,0x3C,0x00,0xC3};
nMajorVersion = nMajorVersion-15;
AsmCode[7]=OffsetAddress32[nMajorVersion][2*nMinorVersion];
AsmCode[8]=OffsetAddress32[nMajorVersion][2*nMinorVersion+1];
ret = WriteProcessMemory(hProcess,pIsEMR,AsmCode,sizeof(AsmCode),&dwNumberOfBytes);
}
if (!ret)
{
uti.Prompt(_T("修改内存模式失败!\n"));
}
else
{
wi.isRemoved = true;
}
CloseHandle(hProcess);
return ret;
}