ATL组件中文路径注册问题

    技术2022-05-11  116

    ATL组件中文路径注册问题

      我曾用ATL写过一个COM组件(MBCS下编译),如果安装在中文路径下的话,注册就会失败.  为什么会失败?  打开ATL的源文件statreg.h,可以找到函数BOOL AddString(LPCOLESTR lpsz),他被组件的UpdateRegistry所调用,他又调用了BOOL AddChar(const TCHAR* pch).问题就出现在这两个函数中。请看:  BOOL AddString(LPCOLESTR lpsz)  {   USES_CONVERSION;   LPCTSTR lpszT = OLE2CT(lpsz);   while (*lpszT)   {    AddChar(lpszT);    lpszT++; // note! @1   }   return TRUE;  }  BOOL AddChar(const TCHAR* pch)  {   if (nPos == nSize) // realloc @3   {    nSize *= 2;    p = (LPTSTR) CoTaskMemRealloc(p, nSize*sizeof(TCHAR));   }   p[nPos++] = *pch;#ifndef _UNICODE   if (IsDBCSLeadByte(*pch))    p[nPos++] = *(pch + 1); file://note! @2#endif   return TRUE;  } 当我们不是使用UNICODE时,如果遇到一个汉字的话,标注@2行识别整个汉字,存入缓冲区.但是pch变量仍然指向汉字的第一个字节,返回到@1行时,lpszT++后指向了该汉字的第二个字节!以后又把该汉字的第二字节当成一个独立的字符再次处理一遍.所以就产生了乱码.(致使组件注册的信息有一部分是错误的) 怎么解决? 由上面的分析,很容易得到解决的办法:  BOOL AddString(LPCOLESTR lpsz)  {   USES_CONVERSION;   LPCTSTR lpszT = OLE2CT(lpsz);   while (*lpszT)   {    AddChar(lpszT);    lpszT++;    }   return TRUE;  }/******************************************************************* * This function cause some error in hanzi. *  Modified by L.C. ,Nov 12th,2001 *******************************************************************//********************************************************************  BOOL AddChar(const TCHAR* pch) ********************************************************************/  BOOL AddChar(const TCHAR* &pch) file://we'll modify the pch value  {   if (nPos == nSize) // realloc   {    nSize *= 2;    p = (LPTSTR) CoTaskMemRealloc(p, nSize*sizeof(TCHAR));   }   p[nPos++] = *pch;#ifndef _UNICODE   if (IsDBCSLeadByte(*pch))/*******************************************************************    p[nPos++] = *(pch + 1); ********************************************************************/    p[nPos++] = *( ++ pch);#endif   return TRUE;  } 还有什么错误? 请观察@3行,如果阅读一下这个类的源代码(180行开始),很明显会有缓冲区溢出的危险:在非UNICODE情况下,nPos要加两次,而进入这段代码时有可能是nPos=nSize-1.如果是这样,恐怕程序的会有一些无法预测的行为(虽然几率很小:在 rgs文件中出现大段中文的可能性不多)。修改实际上比较容易,将if (nPos == nSize) 变为if (nPos == nSize-1)即可。(当然有很多别的方法) 结论 如果你的组件有可能出现在中文路径下的话(使用MBCS),建议你在编译时使用_ATL_STATIC_REGISTRY编译,并且在编译前修改ATL中相关的代码(或自己写注册函数)。否则现有的ATL.DLL会坏了你的好事. 修改现有的类库是很危险的事情。因为他们的调用关系太复杂了.不过,如果他里面有BUG,这也算是一个好方法. 


    最新回复(0)