ATL元件中文路徑註冊問題 (轉)

worldblog發表於2007-12-09
ATL元件中文路徑註冊問題 (轉)[@more@]

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++; ! @1
 }
 return TRUE;
 }
 BOOL AddChar(const TCHAR* pch)
 {
 if (nP== nSize) // realloc @3
 {
 nSize *= 2;
 p = (LPTSTR) CoTaskMemRealloc(p, nSize*sizeof(TCHAR));
 }
 p[nPos++] = *pch;
#ifndef _UNICODE
 if (IsCSLeadByte(*pch))
 p[nPos++] = *(pch + 1); ! @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)  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會壞了你的好事.
 修改現有的類庫是很危險的事情。因為他們的呼叫關係太複雜了.不過,如果他裡面有,這也算是一個
好方法.
 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990167/,如需轉載,請註明出處,否則將追究法律責任。

相關文章