diff --git a/SourceCode/Code2026/CoreLibrary/AecDbEwPipeBase.cpp b/SourceCode/Code2026/CoreLibrary/AecDbEwPipeBase.cpp index f0aa582..e790717 100644 --- a/SourceCode/Code2026/CoreLibrary/AecDbEwPipeBase.cpp +++ b/SourceCode/Code2026/CoreLibrary/AecDbEwPipeBase.cpp @@ -658,6 +658,40 @@ namespace return es != Acad::eOk; } + + // 读端只接受纯文件名:DWG 里存的名字不可信,去掉路径成分防止写到临时目录之外 + CString SanitizeRegionTempName(const CString& sFileName) + { + CString sName = sFileName; + + int nSlash = sName.ReverseFind(_T('\\')); + int nSlash2 = sName.ReverseFind(_T('/')); + if (nSlash2 > nSlash) + nSlash = nSlash2; + + if (nSlash >= 0) + sName = sName.Mid(nSlash + 1); + + // 空名、上跳目录、盘符一律丢弃,退回固定名 + if (sName.IsEmpty() || sName.Find(_T("..")) >= 0 || sName.Find(_T(':')) >= 0) + sName = _T("region_tmp.dat"); + + return sName; + } + + // acisOut 不可用时的兜底:写 errorfile 标记,再让 region 自己写原生数据 + Acad::ErrorStatus WriteRegionNativeFallback(AcDbDwgFiler* pFiler, AcDbRegion* pRegion) + { + pFiler->writeString(_T("errorfile")); + + char pszTxt[7]; + ::memset(pszTxt, 0, sizeof(pszTxt)); + + pFiler->writeUInt32(7); + pFiler->writeBytes(pszTxt, 7); + + return pRegion->dwgOutFields(pFiler); + } } AcDbRegion *AecDbEwPipeBase::RegionFromCurvesDwgInFields(AcDbDwgFiler *pFiler, Adesk::UInt32 nLen) @@ -760,66 +794,92 @@ AcDbRegion* AecDbEwPipeBase::RegionAcisInDwgInFields(AcDbDwgFiler* pFiler) //高版本acis方式 CString sFileName; TCHAR* pszFileName = NULL; - pFiler->readString(&pszFileName); - if (pszFileName != NULL) + if (pFiler->readString(&pszFileName) != Acad::eOk || pszFileName == NULL) { - //Region_%s.dat - sFileName = pszFileName; - acutDelString(pszFileName); - - Adesk::UInt32 nLen = 0; - pFiler->readUInt32(&nLen); - - if (nLen > 0) - { - char* pszTxt = new char[nLen]; - pFiler->readBytes(pszTxt,nLen); - - if (sFileName.CompareNoCase(_T("errorfile")) == 0) - { - //原生写法 - AcDbRegion* pRegion = (AcDbRegion*)AcDbRegion::desc()->create(); - Acad::ErrorStatus es = pRegion->dwgInFields(pFiler); - - return pRegion; - } - else - { - CString sFullPath = FilePath::getSystemTemporaryFolder(); - sFullPath += _T("\\"); - sFullPath += sFileName; - - CFile file; - if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite)) - { - file.Write(pszTxt,nLen); - file.Close(); - - AcDbVoidPtrArray arBodyPtrs; - Acad::ErrorStatus es; - if ( Acad::eOk == (es = AcDbBody::acisIn(sFullPath,arBodyPtrs) ) ) - { - if (arBodyPtrs.length() > 0) - { - AcDbEntity* pEnt = (AcDbEntity*)arBodyPtrs.first(); - AcDbRegion* pRegion = AcDbRegion::cast(pEnt); - if (pRegion != NULL) - { - ::DeleteFile(sFullPath); - delete[] pszTxt; - - return pRegion; - } - //可能其他的合成或boolsubstract... - } - } - ::DeleteFile(sFullPath); - } - } - delete[] pszTxt; - } + acutPrintf(_T("\nAecDbEwPipeBase: 截面读文件名失败。")); + return NULL; } - return NULL; + + //Region_%s.dat + sFileName = pszFileName; + acutDelString(pszFileName); + + Adesk::UInt32 nLen = 0; + pFiler->readUInt32(&nLen); + + if (nLen == 0) + return NULL; + + char* pszTxt = new char[nLen + 1]; + ::memset(pszTxt, 0, nLen + 1); + pFiler->readBytes(pszTxt,nLen); + + if (sFileName.CompareNoCase(_T("errorfile")) == 0) + { + //原生写法 + delete[] pszTxt; + + AcDbRegion* pRegion = (AcDbRegion*)AcDbRegion::desc()->create(); + if (pRegion == NULL) + { + acutPrintf(_T("\nAecDbEwPipeBase: 截面原生读取时创建 region 失败。")); + return NULL; + } + + Acad::ErrorStatus es = pRegion->dwgInFields(pFiler); + if (es != Acad::eOk) + { + acutPrintf(_T("\nAecDbEwPipeBase: 截面原生 dwgInFields 失败,err=%d。"),es); + delete pRegion; + return NULL; + } + return pRegion; + } + + CString sFullPath = FilePath::getSystemTemporaryFolder(); + sFullPath += _T("\\"); + sFullPath += SanitizeRegionTempName(sFileName); + + CFile file; + if (!file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite)) + { + acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件创建失败:%s"),(LPCTSTR)sFullPath); + delete[] pszTxt; + return NULL; + } + + file.Write(pszTxt,nLen); + file.Close(); + delete[] pszTxt; + + AcDbVoidPtrArray arBodyPtrs; + Acad::ErrorStatus es = AcDbBody::acisIn(sFullPath,arBodyPtrs); + if (es != Acad::eOk) + { + acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisIn 失败,len=%u,err=%d。"),nLen,es); + ::DeleteFile(sFullPath); + return NULL; + } + + // acisIn 返回的实体未入库,由调用方负责释放;只留第一个 region,其余丢弃 + AcDbRegion* pRegion = NULL; + for (int i = 0;i < arBodyPtrs.length();i++) + { + AcDbEntity* pEnt = (AcDbEntity*)arBodyPtrs.at(i); + if (pRegion == NULL) + { + pRegion = AcDbRegion::cast(pEnt); + if (pRegion != NULL) + continue; + } + delete pEnt; + } + + if (pRegion == NULL) + acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisIn 未返回 region,len=%u。"),nLen); + + ::DeleteFile(sFullPath); + return pRegion; } AcDbRegion* AecDbEwPipeBase::SectionRegionDwgInFields(AcDbDwgFiler* pFiler,int nVer) @@ -1132,34 +1192,19 @@ Acad::ErrorStatus AecDbEwPipeBase::BaseCurveDwgOutFields(AcDbCurve* pBaseCurve,A return Acad::eOk; } -Acad::ErrorStatus AecDbEwPipeBase::RegionExplodeDwgOutFields(AcDbDwgFiler* pFiler,AcDbVoidPtrArray& arCurPtrs) const -{ - Adesk::UInt32 nCurs = arCurPtrs.length(); - pFiler->writeUInt32(nCurs); - - AcDbCurve* pCurve = NULL; - for (int i = 0;i < arCurPtrs.length();i++) - { - pCurve = (AcDbCurve*)arCurPtrs.at(i); - BaseCurveDwgOutFields(pCurve,pFiler); - delete pCurve; - } - return Acad::eOk; -} - Acad::ErrorStatus AecDbEwPipeBase::RegionAcisoutDwgOutFields(AcDbDwgFiler* pFiler) const { if (m_pRegion == NULL) return Acad::eInvalidInput; //开始写acis方式 - //避免多文档crash + //避免多文档crash:文件名带进程号,同一张图在两个 CAD 实例里同时打开不会互相覆盖 TCHAR szHandleStr[19]; memset(szHandleStr,0,sizeof(szHandleStr) ); objectId().handle().getIntoAsciiBuffer(szHandleStr); CString sFileName; - sFileName.Format(_T("Region_%s.dat"),szHandleStr); + sFileName.Format(_T("Region_%lu_%s.dat"),(unsigned long)::GetCurrentProcessId(),szHandleStr); CString sFullPath = FilePath::getSystemTemporaryFolder(); sFullPath += _T("\\"); @@ -1168,110 +1213,67 @@ Acad::ErrorStatus AecDbEwPipeBase::RegionAcisoutDwgOutFields(AcDbDwgFiler* pFile AcDbVoidPtrArray arBodyPtrs; arBodyPtrs.append(m_pRegion); - Acad::ErrorStatus es; - if (Acad::eOk == (es = AcDbBody::acisOut(sFullPath, arBodyPtrs))) + Acad::ErrorStatus es = AcDbBody::acisOut(sFullPath, arBodyPtrs); + if (Acad::eOk != es) { - CFile file; - if (file.Open(sFullPath, CFile::modeRead)) - { - //确认REGION不会超过32位数量级字节 - //强制转换兼容可能的07-09CAD - ULONGLONG dwFileLength = file.GetLength(); - Adesk::UInt32 nLen = (Adesk::UInt32)dwFileLength; - - char* pszTxt = new char[nLen]; - file.Read(pszTxt, nLen); - file.Close(); - - pFiler->writeString((LPCTSTR)sFileName); - pFiler->writeUInt32(nLen); - pFiler->writeBytes(pszTxt,nLen); - - ::DeleteFile(sFullPath); - delete[] pszTxt; - return Acad::eOk; - } - else - { - pFiler->writeString(_T("errorfile")); - - char* pszTxt = new char[7]; - memset(pszTxt,0,7); - - pFiler->writeUInt32(7); - - pFiler->writeBytes(pszTxt,7); - - //原生写法 - es = m_pRegion->dwgOutFields(pFiler); - - return es; - } + acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisOut 失败,handle=%s,err=%d,改用原生写法。"),szHandleStr,es); + ::DeleteFile(sFullPath); + return WriteRegionNativeFallback(pFiler, m_pRegion); } - else + + CFile file; + if (!file.Open(sFullPath, CFile::modeRead)) { - pFiler->writeString(_T("errorfile")); - - char* pszTxt = new char[7]; - memset(pszTxt,0,7); - - pFiler->writeUInt32(7); - - pFiler->writeBytes(pszTxt,7); - - //原生写法 - es = m_pRegion->dwgOutFields(pFiler); - - return es; + acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件打开失败,handle=%s,改用原生写法。"),szHandleStr); + ::DeleteFile(sFullPath); + return WriteRegionNativeFallback(pFiler, m_pRegion); } - return Acad::eOutOfMemory; + + //确认REGION不会超过32位数量级字节 + //强制转换兼容可能的07-09CAD + ULONGLONG dwFileLength = file.GetLength(); + Adesk::UInt32 nLen = (Adesk::UInt32)dwFileLength; + + char* pszTxt = new char[nLen + 1]; + ::memset(pszTxt, 0, nLen + 1); + + UINT nRead = file.Read(pszTxt, nLen); + file.Close(); + + if (nLen == 0 || nRead != nLen) + { + // 空文件或短读:尾部是未初始化内存,不能写进 DWG + acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件异常,handle=%s,期望%u字节实读%u字节,改用原生写法。") + ,szHandleStr,nLen,nRead); + ::DeleteFile(sFullPath); + delete[] pszTxt; + return WriteRegionNativeFallback(pFiler, m_pRegion); + } + + pFiler->writeString((LPCTSTR)sFileName); + pFiler->writeUInt32(nLen); + pFiler->writeBytes(pszTxt,nLen); + + ::DeleteFile(sFullPath); + delete[] pszTxt; + return Acad::eOk; } Acad::ErrorStatus AecDbEwPipeBase::SectionRegionDwgOutFields(AcDbDwgFiler* pFiler,int nVer) const { assertReadEnabled(); - if (m_pRegion != NULL) - { - if (nVer < 4)//旧版本,保持原样,有错误漏洞 - { - AcDbVoidPtrArray arCurPtrs; - m_pRegion->explode(arCurPtrs); + UNREFERENCED_PARAMETER(nVer); - if (!arCurPtrs.isEmpty()) - { - return RegionExplodeDwgOutFields(pFiler,arCurPtrs); - } - else - { - //旧版本错误漏洞 - //旧版本不考虑 nVer已经升级 - //... - } - } - else - { - AcDbVoidPtrArray arCurPtrs; - m_pRegion->explode(arCurPtrs); + if (m_pRegion == NULL) + return Acad::eOk; - //如果炸碎成功 - if (!arCurPtrs.isEmpty()) - { - //轻量化写法 - return RegionExplodeDwgOutFields(pFiler,arCurPtrs); - } - else - { - //补救措施,重量化写法 - //写入长度0 旧版本<4 情况不考虑 nVer已经升级 - Adesk::UInt32 nCurs = 0; - pFiler->writeUInt32(nCurs); + // 统一写 SAT:nLen = 0 是读取端识别 SAT 通道的标志,旧版本插件同样识别。 + // 曲线通道只用于读老图纸,写路径已退役,不再按截面类型分流 + Adesk::UInt32 nCurs = 0; + pFiler->writeUInt32(nCurs); - return RegionAcisoutDwgOutFields(pFiler); - } - } - } - return Acad::eOk; + return RegionAcisoutDwgOutFields(pFiler); } Acad::ErrorStatus AecDbEwPipeBase::DefaultNo() diff --git a/SourceCode/Code2026/inc/AecDbEwPipeBase.h b/SourceCode/Code2026/inc/AecDbEwPipeBase.h index 0af3107..02829f8 100644 --- a/SourceCode/Code2026/inc/AecDbEwPipeBase.h +++ b/SourceCode/Code2026/inc/AecDbEwPipeBase.h @@ -149,7 +149,6 @@ protected: Acad::ErrorStatus BaseCurveDwgOutFields(AcDbCurve* pBaseCurve,AcDbDwgFiler* pFiler) const; Acad::ErrorStatus RegionAcisoutDwgOutFields(AcDbDwgFiler* pFiler) const; - Acad::ErrorStatus RegionExplodeDwgOutFields(AcDbDwgFiler* pFiler,AcDbVoidPtrArray& arCurPtrs) const; Acad::ErrorStatus SectionRegionDwgOutFields(AcDbDwgFiler* pFiler,int nVer) const; Acad::ErrorStatus AddDimPoints(AcDbGripDataPtrArray& grips,const AcGeVector3d& curViewDir,