mlstra.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 23k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. // MLStrA.cpp : Implementation of CMLStrA
  2. #include "private.h"
  3. #ifndef NEWMLSTR
  4. #include "mlstr.h"
  5. #ifdef ASTRIMPL
  6. #include "mlswalk.h"
  7. #include "mlsbwalk.h"
  8. #endif
  9. /////////////////////////////////////////////////////////////////////////////
  10. // CMLStrA
  11. #ifdef ASTRIMPL
  12. CMLStrA::CMLStrA(void) :
  13.     m_pMLCPs(NULL)
  14. {
  15. }
  16. CMLStrA::~CMLStrA(void)
  17. {
  18.     if (m_pMLCPs)
  19.         m_pMLCPs->Release();
  20. }
  21. #endif
  22. STDMETHODIMP CMLStrA::Sync(BOOL fNoAccess)
  23. {
  24.     ASSERT_THIS;
  25.     return GetOwner()->Sync(fNoAccess);
  26. }
  27. STDMETHODIMP CMLStrA::GetLength(long* plLen)
  28. {
  29.     ASSERT_THIS;
  30.     return GetOwner()->GetLength(plLen);
  31. }
  32. STDMETHODIMP CMLStrA::SetMLStr(long lDestPos, long lDestLen, IUnknown* pSrcMLStr, long lSrcPos, long lSrcLen)
  33. {
  34.     ASSERT_THIS;
  35.     return GetOwner()->SetMLStr(lDestPos, lDestLen, pSrcMLStr, lSrcPos, lSrcLen);
  36. }
  37. STDMETHODIMP CMLStrA::GetMLStr(long lSrcPos, long lSrcLen, IUnknown* pUnkOuter, DWORD dwClsContext, const IID* piid, IUnknown** ppDestMLStr, long* plDestPos, long* plDestLen)
  38. {
  39.     ASSERT_THIS;
  40.     return GetOwner()->GetMLStr(lSrcPos, lSrcLen, pUnkOuter, dwClsContext, piid, ppDestMLStr, plDestPos, plDestLen);
  41. }
  42. STDMETHODIMP CMLStrA::SetAStr(long lDestPos, long lDestLen, UINT uCodePage, const CHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  43. {
  44. #ifdef ASTRIMPL
  45.     ASSERT_THIS;
  46.     ASSERT_READ_BLOCK(pszSrc, cchSrc);
  47.     ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  48.     ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  49.     POWNER const pOwner = GetOwner();
  50.     HRESULT hr = pOwner->CheckThread();
  51.     CMLStr::CLock Lock(TRUE, pOwner, hr);
  52.     long cchDestPos;
  53.     long cchDestLen;
  54.     long cchActual;
  55.     long lActualLen;
  56.     if (SUCCEEDED(hr) && (pOwner->GetBufFlags() & MLSTR_WRITE))
  57.         hr = E_INVALIDARG; // Not writable StrBuf; TODO: Replace StrBuf in this case if allowed
  58.     if (SUCCEEDED(hr) &&
  59.         SUCCEEDED(hr = pOwner->PrepareMLStrBuf()) &&
  60.         SUCCEEDED(hr = pOwner->RegularizePosLen(&lDestPos, &lDestLen)) &&
  61.         SUCCEEDED(hr = pOwner->GetCCh(0, lDestPos, &cchDestPos)) &&
  62.         SUCCEEDED(hr = pOwner->GetCCh(cchDestPos, lDestLen, &cchDestLen)))
  63.     {
  64.         IMLangStringBufA* const pMLStrBufA = pOwner->GetMLStrBufA();
  65.         if (uCodePage == CP_ACP)
  66.             uCodePage = ::GetACP();
  67.         if (pMLStrBufA && uCodePage == pOwner->GetCodePage())
  68.         {
  69.             if (cchSrc > cchDestLen)
  70.             {
  71.                 hr = pMLStrBufA->Insert(cchDestPos, cchSrc - cchDestLen, (pcchActual || plActualLen) ? &cchSrc : NULL);
  72.                 cchSrc += cchDestLen;
  73.             }
  74.             else if  (cchSrc < cchDestLen)
  75.             {
  76.                 hr = pMLStrBufA->Delete(cchDestPos, cchDestLen - cchSrc);
  77.             }
  78.             CMLStrBufWalkA BufWalk(pMLStrBufA, cchDestPos, cchSrc, (pcchActual || plActualLen));
  79.             lActualLen = 0;
  80.             while (BufWalk.Lock(hr))
  81.             {
  82.                 long lLen;
  83.                 if (plActualLen)
  84.                     hr = pOwner->CalcLenA(uCodePage, pszSrc, BufWalk.GetCCh(), &lLen);
  85.                 if (SUCCEEDED(hr))
  86.                 {
  87.                     lActualLen += lLen;
  88.                     ::memcpy(BufWalk.GetStr(), pszSrc, sizeof(CHAR) * BufWalk.GetCCh());
  89.                     pszSrc += BufWalk.GetCCh();
  90.                 }
  91.                 BufWalk.Unlock(hr);
  92.             }
  93.             cchActual = BufWalk.GetDoneCCh();
  94.         }
  95.         else
  96.         {
  97.             IMLangStringWStr* pMLStrW;
  98.             if (SUCCEEDED(hr = pOwner->QueryInterface(IID_IMLangStringWStr, (void**)&pMLStrW)))
  99.             {
  100.                 CMLStrWalkW StrWalk(pMLStrW, lDestPos, lDestLen, MLSTR_WRITE, (pcchActual || plActualLen));
  101.                 cchActual = 0;
  102.                 lActualLen = 0;
  103.                 while (StrWalk.Lock(hr))
  104.                 {
  105.                     long cchWrittenA;
  106.                     long lWrittenLen;
  107.                     if (SUCCEEDED(hr = pOwner->ConvAStrToWStr(uCodePage, pszSrc, cchSrc, StrWalk.GetStr(), StrWalk.GetCCh(), &cchWrittenA, NULL, &lWrittenLen)))
  108.                     {
  109.                         pszSrc += cchWrittenA;
  110.                         cchSrc -= cchWrittenA;
  111.                         cchActual += cchWrittenA;
  112.                         lActualLen += lWrittenLen;
  113.                     }
  114.                     StrWalk.Unlock(hr, lWrittenLen);
  115.                 }
  116.                 pMLStrW->Release();
  117.             }
  118.         }
  119.     }
  120.     if (SUCCEEDED(hr))
  121.     {
  122.         if (pcchActual)
  123.             *pcchActual = cchActual;
  124.         if (plActualLen)
  125.             *plActualLen = lActualLen;
  126.     }
  127.     else
  128.     {
  129.         if (pcchActual)
  130.             *pcchActual = 0;
  131.         if (plActualLen)
  132.             *plActualLen = 0;
  133.     }
  134.     return hr;
  135. #else
  136.     return E_NOTIMPL; // !ASTRIMPL
  137. #endif
  138. }
  139. STDMETHODIMP CMLStrA::SetStrBufA(long lDestPos, long lDestLen, UINT uCodePage, IMLangStringBufA* pSrcBuf, long* pcchActual, long* plActualLen)
  140. {
  141.     ASSERT_THIS;
  142.     return GetOwner()->SetStrBufCommon(this, lDestPos, lDestLen, uCodePage, NULL, pSrcBuf, pcchActual, plActualLen);
  143. }
  144. STDMETHODIMP CMLStrA::GetAStr(long lSrcPos, long lSrcLen, UINT uCodePageIn, UINT* puCodePageOut, CHAR* pszDest, long cchDest, long* pcchActual, long* plActualLen)
  145. {
  146.     ASSERT_THIS;
  147.     ASSERT_WRITE_PTR_OR_NULL(puCodePageOut);
  148.     ASSERT_WRITE_BLOCK_OR_NULL(pszDest, cchDest);
  149.     ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  150.     ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  151.     POWNER const pOwner = GetOwner();
  152.     HRESULT hr = pOwner->CheckThread();
  153. #ifdef ASTRIMPL
  154.     CMLStr::CLock Lock(FALSE, pOwner, hr);
  155. #endif
  156.     long cchSrcPos;
  157.     long cchSrcLen;
  158.     long cchActual;
  159.     long lActualLen;
  160. #ifndef ASTRIMPL
  161.     if (SUCCEEDED(hr = m_pOwner->CheckThread()) &&
  162.         (m_pOwner->IsLocked() || puCodePageOut || uCodePageIn != m_pOwner->GetCodePage())) // !ASTRIMPL
  163.     {
  164.         hr = E_INVALIDARG;
  165.     }
  166. #endif
  167.     if (SUCCEEDED(hr) &&
  168.         SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcLen)) &&
  169.         SUCCEEDED(hr = pOwner->GetCCh(0, lSrcPos, &cchSrcPos)) &&
  170.         SUCCEEDED(hr = pOwner->GetCCh(cchSrcPos, lSrcLen, &cchSrcLen)))
  171.     {
  172. #ifdef ASTRIMPL
  173.         IMLangStringBufA* const pMLStrBufA = pOwner->GetMLStrBufA();
  174.         if (pszDest)
  175.             cchActual = min(cchSrcLen, cchDest);
  176.         else
  177.             cchActual = cchSrcLen;
  178.         if (uCodePageIn == CP_ACP)
  179.             uCodePageIn = ::GetACP();
  180.         if (pMLStrBufA && (puCodePageOut || uCodePageIn == pOwner->GetCodePage()))
  181.         {
  182.             uCodePageIn = pOwner->GetCodePage();
  183.             CMLStrBufWalkA BufWalk(pMLStrBufA, cchSrcPos, cchActual, (pcchActual || plActualLen));
  184.             lActualLen = 0;
  185.             while (BufWalk.Lock(hr))
  186.             {
  187.                 long lLen;
  188.                 if (plActualLen)
  189.                     hr = pOwner->CalcLenA(uCodePageIn, BufWalk.GetStr(), BufWalk.GetCCh(), &lLen);
  190.                 if (SUCCEEDED(hr))
  191.                 {
  192.                     lActualLen += lLen;
  193.                     if (pszDest)
  194.                     {
  195.                         ::memcpy(pszDest, BufWalk.GetStr(), sizeof(CHAR) * BufWalk.GetCCh());
  196.                         pszDest += BufWalk.GetCCh();
  197.                     }
  198.                 }
  199.                 BufWalk.Unlock(hr);
  200.             }
  201.             cchActual = BufWalk.GetDoneCCh();
  202.         }
  203.         else
  204.         {
  205.             IMLangStringWStr* pMLStrW;
  206.             if (SUCCEEDED(hr = pOwner->QueryInterface(IID_IMLangStringWStr, (void**)&pMLStrW)))
  207.             {
  208.                 BOOL fDontHaveCodePageIn = (puCodePageOut != 0);
  209.                 CMLStrWalkW StrWalk(pMLStrW, lSrcPos, lSrcLen, (pcchActual || plActualLen));
  210.                 cchActual = 0;
  211.                 while (StrWalk.Lock(hr))
  212.                 {
  213.                     LCID locale;
  214.                     UINT uLocaleCodePage;
  215.                     DWORD dwLocaleCodePages;
  216.                     DWORD dwStrCodePages;
  217.                     long cchWritten;
  218.                     long lWrittenLen;
  219.                     if (fDontHaveCodePageIn &&
  220.                         SUCCEEDED(hr = pOwner->GetLocale(lSrcPos, lSrcLen, &locale, NULL, NULL)) &&
  221.                         SUCCEEDED(hr = ::LocaleToCodePage(locale, &uLocaleCodePage)) &&
  222.                         SUCCEEDED(hr = PrepareMLangCodePages()) &&
  223.                         SUCCEEDED(hr = GetMLangCodePages()->CodePageToCodePages(uLocaleCodePage, &dwLocaleCodePages)) &&
  224.                         SUCCEEDED(hr = GetMLangCodePages()->GetStrCodePages(StrWalk.GetStr(), StrWalk.GetCCh(), dwLocaleCodePages, &dwStrCodePages, NULL)))
  225.                     {
  226.                         fDontHaveCodePageIn = FALSE;
  227.                         hr = GetMLangCodePages()->CodePagesToCodePage(dwStrCodePages, uLocaleCodePage, &uCodePageIn);
  228.                     }
  229.                     if (SUCCEEDED(hr) &&
  230.                         SUCCEEDED(hr = pOwner->ConvWStrToAStr(pcchActual || plActualLen, uCodePageIn, StrWalk.GetStr(), StrWalk.GetCCh(), pszDest, cchDest, &cchWritten, NULL, &lWrittenLen)))
  231.                     {
  232.                         pszDest += cchWritten;
  233.                         cchDest -= cchWritten;
  234.                         cchActual += cchWritten;
  235.                     }
  236.                     StrWalk.Unlock(hr, lWrittenLen);
  237.                 }
  238.                 lActualLen = StrWalk.GetDoneLen();
  239.                 pMLStrW->Release();
  240.             }
  241.         }
  242.     }
  243. #else
  244.         if (pszDest)
  245.         {
  246.             hr = E_FAIL; // TODO: Not implemented in this version
  247.         }
  248.         else
  249.         {
  250.             cchActual = cchSrcLen;
  251.         }
  252.     }
  253.     if (SUCCEEDED(hr) && plActualLen)
  254.         hr = m_pOwner->CalcLenA(m_pOwner->GetCodePage(), 0, cchActual, &lActualLen);
  255. #endif
  256.     if (SUCCEEDED(hr))
  257.     {
  258. #ifdef ASTRIMPL
  259.         if (puCodePageOut)
  260.             *puCodePageOut = uCodePageIn;
  261. #endif
  262.         if (pcchActual)
  263.             *pcchActual = cchActual;
  264.         if (plActualLen)
  265.             *plActualLen = lActualLen;
  266.     }
  267.     else
  268.     {
  269.         if (puCodePageOut)
  270.             *puCodePageOut = 0;
  271.         if (pcchActual)
  272.             *pcchActual = 0;
  273.         if (plActualLen)
  274.             *plActualLen = 0;
  275.     }
  276.     return hr;
  277. }
  278. STDMETHODIMP CMLStrA::GetStrBufA(long lSrcPos, long lSrcMaxLen, UINT* puDestCodePage, IMLangStringBufA** ppDestBuf, long* plDestLen)
  279. {
  280. #ifdef ASTRIMPL
  281.     ASSERT_THIS;
  282.     ASSERT_WRITE_PTR_OR_NULL(puDestCodePage);
  283.     ASSERT_WRITE_PTR_OR_NULL(ppDestBuf);
  284.     ASSERT_WRITE_PTR_OR_NULL(plDestLen);
  285.     POWNER const pOwner = GetOwner();
  286.     HRESULT hr = pOwner->CheckThread();
  287.     CMLStr::CLock Lock(FALSE, pOwner, hr);
  288.     IMLangStringBufA* pMLStrBufA;
  289.     if (SUCCEEDED(hr) &&
  290.         SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcMaxLen)) &&
  291.         lSrcMaxLen <= 0)
  292.     {
  293.         hr = E_INVALIDARG;
  294.     }
  295.     if (SUCCEEDED(hr))
  296.     {
  297.         pMLStrBufA = pOwner->GetMLStrBufA();
  298.         if (!pMLStrBufA)
  299.             hr = MLSTR_E_STRBUFNOTAVAILABLE;
  300.     }
  301.     if (SUCCEEDED(hr))
  302.     {
  303.         if (puDestCodePage)
  304.             *puDestCodePage = pOwner->GetCodePage();
  305.         if (ppDestBuf)
  306.         {
  307.             pMLStrBufA->AddRef();
  308.             *ppDestBuf = pMLStrBufA;
  309.         }
  310.         if (plDestLen)
  311.             *plDestLen = lSrcMaxLen;
  312.     }
  313.     else
  314.     {
  315.         if (puDestCodePage)
  316.             *puDestCodePage = 0;
  317.         if (ppDestBuf)
  318.             *ppDestBuf = NULL;
  319.         if (plDestLen)
  320.             *plDestLen = 0;
  321.     }
  322.     return hr;
  323. #else
  324.     return E_NOTIMPL; // !ASTRIMPL
  325. #endif
  326. }
  327. STDMETHODIMP CMLStrA::LockAStr(long lSrcPos, long lSrcLen, long lFlags, UINT uCodePageIn, long cchRequest, UINT* puCodePageOut, CHAR** ppszDest, long* pcchDest, long* plDestLen)
  328. {
  329. #ifdef ASTRIMPL
  330.     ASSERT_THIS;
  331.     ASSERT_WRITE_PTR_OR_NULL(puCodePageOut);
  332.     ASSERT_WRITE_PTR_OR_NULL(ppszDest);
  333.     ASSERT_WRITE_PTR_OR_NULL(pcchDest);
  334.     ASSERT_WRITE_PTR_OR_NULL(plDestLen);
  335.     POWNER const pOwner = GetOwner();
  336.     HRESULT hr = pOwner->CheckThread();
  337.     CMLStr::CLock Lock(lFlags & MLSTR_WRITE, pOwner, hr);
  338.     long cchSrcPos;
  339.     long cchSrcLen;
  340.     CHAR* pszBuf = NULL;
  341.     long cchBuf;
  342.     long lLockLen;
  343.     BOOL fDirectLock;
  344.     if (SUCCEEDED(hr) && (!lFlags || (lFlags & ~pOwner->GetBufFlags() & MLSTR_WRITE)))
  345.         hr = E_INVALIDARG; // No flags specified, or not writable StrBuf; TODO: Replace StrBuf in this case if allowed
  346.     if (!(lFlags & MLSTR_WRITE))
  347.         cchRequest = 0;
  348.     if (SUCCEEDED(hr) &&
  349.         SUCCEEDED(hr = pOwner->PrepareMLStrBuf()) &&
  350.         SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcLen)) &&
  351.         SUCCEEDED(hr = pOwner->GetCCh(0, lSrcPos, &cchSrcPos)) &&
  352.         SUCCEEDED(hr = pOwner->GetCCh(cchSrcPos, lSrcLen, &cchSrcLen)))
  353.     {
  354.         IMLangStringBufA* const pMLStrBufA = pOwner->GetMLStrBufA();
  355.         fDirectLock = (pMLStrBufA && (puCodePageOut || uCodePageIn == pOwner->GetCodePage()));
  356.         if (fDirectLock)
  357.         {
  358.             long cchInserted;
  359.             long cchLockLen = cchSrcLen;
  360.             if (puCodePageOut)
  361.                 hr = GetAStr(lSrcPos, lSrcLen, 0, &uCodePageIn, NULL, 0, NULL, NULL);
  362.             if (SUCCEEDED(hr) &&
  363.                 cchRequest > cchSrcLen &&
  364.                 SUCCEEDED(hr = pMLStrBufA->Insert(cchSrcPos + cchSrcLen, cchRequest - cchSrcLen, &cchInserted)))
  365.             {
  366.                 pOwner->SetBufCCh(pOwner->GetBufCCh() + cchInserted);
  367.                 cchLockLen += cchInserted;
  368.                 if (!pcchDest && cchLockLen < cchRequest)
  369.                     hr = E_OUTOFMEMORY; // Can't insert in StrBuf
  370.             }
  371.             if (SUCCEEDED(hr) &&
  372.                 SUCCEEDED(hr = pMLStrBufA->LockBuf(cchSrcPos, cchLockLen, &pszBuf, &cchBuf)) &&
  373.                 !pcchDest && cchBuf < max(cchSrcLen, cchRequest))
  374.             {
  375.                 hr = E_OUTOFMEMORY; // Can't lock StrBuf
  376.             }
  377.             if (plDestLen && SUCCEEDED(hr))
  378.                 hr = pOwner->CalcLenA(uCodePageIn, pszBuf, cchBuf, &lLockLen);
  379.         }
  380.         else
  381.         {
  382.             long cchSize;
  383.             if (SUCCEEDED(hr = pOwner->CalcBufSizeA(lSrcLen, &cchSize)))
  384.             {
  385.                 cchBuf = max(cchSize, cchRequest);
  386.                 hr = pOwner->MemAlloc(sizeof(*pszBuf) * cchBuf, (void**)&pszBuf);
  387.             }
  388.             if (SUCCEEDED(hr) && ((lFlags & MLSTR_READ) || puCodePageOut))
  389.                 hr = GetAStr(lSrcPos, lSrcLen,  uCodePageIn, (puCodePageOut) ? &uCodePageIn : NULL, (lFlags & MLSTR_READ) ? pszBuf : NULL, cchBuf, (pcchDest) ? &cchBuf : NULL, (plDestLen) ? &lLockLen : NULL);
  390.         }
  391.     }
  392.     if (SUCCEEDED(hr) &&
  393.         SUCCEEDED(hr = Lock.FallThrough()))
  394.     {
  395.         hr = pOwner->GetLockInfo()->Lock((fDirectLock) ? pOwner->UnlockAStrDirect : pOwner->UnlockAStrIndirect, lFlags, uCodePageIn, pszBuf, lSrcPos, lSrcLen, cchSrcPos, cchBuf);
  396.     }
  397.     if (SUCCEEDED(hr))
  398.     {
  399.         if (puCodePageOut)
  400.             *puCodePageOut = uCodePageIn;
  401.         if (ppszDest)
  402.             *ppszDest = pszBuf;
  403.         if (pcchDest)
  404.             *pcchDest = cchBuf;
  405.         if (plDestLen)
  406.             *plDestLen = lLockLen;
  407.     }
  408.     else
  409.     {
  410.         if (pszBuf)
  411.         {
  412.             if (fDirectLock)
  413.                 pOwner->GetMLStrBufA()->UnlockBuf(pszBuf, 0, 0);
  414.             else
  415.                 pOwner->MemFree(pszBuf);
  416.         }
  417.         if (puCodePageOut)
  418.             *puCodePageOut = 0;
  419.         if (ppszDest)
  420.             *ppszDest = NULL;
  421.         if (pcchDest)
  422.             *pcchDest = 0;
  423.         if (plDestLen)
  424.             *plDestLen = 0;
  425.     }
  426.     return hr;
  427. #else
  428.     return E_NOTIMPL; // !ASTRIMPL
  429. #endif
  430. }
  431. STDMETHODIMP CMLStrA::UnlockAStr(const CHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  432. {
  433. #ifdef ASTRIMPL
  434.     ASSERT_THIS;
  435.     ASSERT_READ_BLOCK(pszSrc, cchSrc);
  436.     ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  437.     ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  438.     return GetOwner()->UnlockStrCommon(pszSrc, cchSrc, pcchActual, plActualLen);
  439. #else
  440.     return E_NOTIMPL; // !ASTRIMPL
  441. #endif
  442. }
  443. STDMETHODIMP CMLStrA::SetLocale(long lDestPos, long lDestLen, LCID locale)
  444. {
  445.     ASSERT_THIS;
  446.     return GetOwner()->SetLocale(lDestPos, lDestLen, locale);
  447. }
  448. STDMETHODIMP CMLStrA::GetLocale(long lSrcPos, long lSrcMaxLen, LCID* plocale, long* plLocalePos, long* plLocaleLen)
  449. {
  450.     ASSERT_THIS;
  451.     return GetOwner()->GetLocale(lSrcPos, lSrcMaxLen, plocale, plLocalePos, plLocaleLen);
  452. }
  453. #else // NEWMLSTR
  454. #include "mlstr.h"
  455. /////////////////////////////////////////////////////////////////////////////
  456. // CMLStrA
  457. CMLStrA::CMLStrA(void) :
  458.     m_pAttrAStr(NULL),
  459.     m_pAttrLocale(NULL),
  460.     m_dwAttrAStrCookie(NULL),
  461.     m_dwAttrLocaleCookie(NULL)
  462. {
  463.     ::InitializeCriticalSection(&m_cs);
  464. }
  465. CMLStrA::~CMLStrA(void)
  466. {
  467.     if (m_dwAttrLocaleCookie)
  468.         GetOwner()->UnregisterAttr(m_dwAttrLocaleCookie);
  469.     if (m_dwAttrAStrCookie)
  470.         GetOwner()->UnregisterAttr(m_dwAttrAStrCookie);
  471.     if (m_pAttrLocale)
  472.         m_pAttrLocale->Release();
  473.     if (m_pAttrAStr)
  474.         m_pAttrAStr->Release();
  475.     ::DeleteCriticalSection(&m_cs);
  476. }
  477. HRESULT CMLStrA::GetAttrAStrReal(IMLStrAttrAStr** ppAttr)
  478. {
  479.     HRESULT hr = S_OK;
  480.     ::EnterCriticalSection(&m_cs);
  481.     if (!m_pAttrAStr)
  482.     {
  483.         IMLStrAttrAStr* pAttr;
  484.         hr = ::CoCreateInstance(CLSID_CMLStrAttrAStr, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pAttr);
  485.         if (SUCCEEDED(hr))
  486.             hr = GetOwner()->RegisterAttr(pAttr, &m_dwAttrAStrCookie);
  487.         if (SUCCEEDED(hr))
  488.         {
  489.             pAttr->Release();
  490.             hr = GetOwner()->FindAttr(IID_IMLStrAttrAStr, 0, (IUnknown**)&pAttr);
  491.         }
  492.         if (SUCCEEDED(hr))
  493.             m_pAttrAStr = pAttr;
  494.     }
  495.     if (ppAttr)
  496.         *ppAttr = m_pAttrAStr;
  497.     ::LeaveCriticalSection(&m_cs);
  498.     return hr;
  499. }
  500. HRESULT CMLStrA::GetAttrLocaleReal(IMLStrAttrLocale** ppAttr)
  501. {
  502.     HRESULT hr = S_OK;
  503.     ::EnterCriticalSection(&m_cs);
  504.     if (!m_pAttrLocale)
  505.     {
  506.         IMLStrAttrLocale* pAttr;
  507.         hr = ::CoCreateInstance(CLSID_CMLStrAttrLocale, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pAttr);
  508.         if (SUCCEEDED(hr))
  509.             hr = GetOwner()->RegisterAttr(pAttr, &m_dwAttrLocaleCookie);
  510.         if (SUCCEEDED(hr))
  511.         {
  512.             pAttr->Release();
  513.             hr = GetOwner()->FindAttr(IID_IMLStrAttrLocale, 0, (IUnknown**)&pAttr);
  514.         }
  515.         if (SUCCEEDED(hr))
  516.             m_pAttrLocale = pAttr;
  517.     }
  518.     if (ppAttr)
  519.         *ppAttr = m_pAttrLocale;
  520.     ::LeaveCriticalSection(&m_cs);
  521.     return hr;
  522. }
  523. STDMETHODIMP CMLStrA::LockMLStr(long lPos, long lLen, DWORD dwFlags, DWORD* pdwCookie, long* plActualPos, long* plActualLen)
  524. {
  525.     ASSERT_THIS;
  526.     return GetOwner()->LockMLStr(lPos, lLen, dwFlags, pdwCookie, plActualPos, plActualLen);
  527. }
  528. STDMETHODIMP CMLStrA::UnlockMLStr(DWORD dwCookie)
  529. {
  530.     ASSERT_THIS;
  531.     return GetOwner()->UnlockMLStr(dwCookie);
  532. }
  533. STDMETHODIMP CMLStrA::GetLength(long* plLen)
  534. {
  535.     ASSERT_THIS;
  536.     return GetOwner()->GetLength(plLen);
  537. }
  538. STDMETHODIMP CMLStrA::SetMLStr(long lDestPos, long lDestLen, IUnknown* pSrcMLStr, long lSrcPos, long lSrcLen)
  539. {
  540.     ASSERT_THIS;
  541.     return GetOwner()->SetMLStr(lDestPos, lDestLen, pSrcMLStr, lSrcPos, lSrcLen);
  542. }
  543. STDMETHODIMP CMLStrA::RegisterAttr(IUnknown* pUnk, DWORD* pdwCookie)
  544. {
  545.     ASSERT_THIS;
  546.     return GetOwner()->RegisterAttr(pUnk, pdwCookie);
  547. }
  548. STDMETHODIMP CMLStrA::UnregisterAttr(DWORD dwCookie)
  549. {
  550.     ASSERT_THIS;
  551.     return GetOwner()->UnregisterAttr(dwCookie);
  552. }
  553. STDMETHODIMP CMLStrA::EnumAttr(IEnumUnknown** ppEnumUnk)
  554. {
  555.     ASSERT_THIS;
  556.     return GetOwner()->EnumAttr(ppEnumUnk);
  557. }
  558. STDMETHODIMP CMLStrA::FindAttr(REFIID riid, LPARAM lParam, IUnknown** ppUnk)
  559. {
  560.     ASSERT_THIS;
  561.     return GetOwner()->FindAttr(riid, lParam, ppUnk);
  562. }
  563. STDMETHODIMP CMLStrA::SetAStr(long lDestPos, long lDestLen, UINT uCodePage, const CHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  564. {
  565.     ASSERT_THIS;
  566.     IMLStrAttrAStr* pAttr;
  567.     HRESULT hr = GetAttrAStr(&pAttr);
  568.     if (SUCCEEDED(hr))
  569.         hr = pAttr->SetAStr(lDestPos, lDestLen, uCodePage, pszSrc, cchSrc, pcchActual, plActualLen);
  570.     return hr;
  571. }
  572. STDMETHODIMP CMLStrA::SetStrBufA(long lDestPos, long lDestLen, UINT uCodePage, IMLangStringBufA* pSrcBuf, long* pcchActual, long* plActualLen)
  573. {
  574.     ASSERT_THIS;
  575.     IMLStrAttrAStr* pAttr;
  576.     HRESULT hr = GetAttrAStr(&pAttr);
  577.     if (SUCCEEDED(hr))
  578.         hr = pAttr->SetStrBufA(lDestPos, lDestLen, uCodePage, pSrcBuf, pcchActual, plActualLen);
  579.     return hr;
  580. }
  581. STDMETHODIMP CMLStrA::GetAStr(long lSrcPos, long lSrcLen, UINT uCodePageIn, UINT* puCodePageOut, CHAR* pszDest, long cchDest, long* pcchActual, long* plActualLen)
  582. {
  583.     ASSERT_THIS;
  584.     IMLStrAttrAStr* pAttr;
  585.     HRESULT hr = GetAttrAStr(&pAttr);
  586.     if (SUCCEEDED(hr))
  587.         hr = pAttr->GetAStr(lSrcPos, lSrcLen, uCodePageIn, puCodePageOut, pszDest, cchDest, pcchActual, plActualLen);
  588.     return hr;
  589. }
  590. STDMETHODIMP CMLStrA::GetStrBufA(long lSrcPos, long lSrcMaxLen, UINT* puDestCodePage, IMLangStringBufA** ppDestBuf, long* plDestLen)
  591. {
  592.     ASSERT_THIS;
  593.     IMLStrAttrAStr* pAttr;
  594.     HRESULT hr = GetAttrAStr(&pAttr);
  595.     if (SUCCEEDED(hr))
  596.         hr = pAttr->GetStrBufA(lSrcPos, lSrcMaxLen, puDestCodePage, ppDestBuf, plDestLen);
  597.     return hr;
  598. }
  599. STDMETHODIMP CMLStrA::LockAStr(long lSrcPos, long lSrcLen, long lFlags, UINT uCodePageIn, long cchRequest, UINT* puCodePageOut, CHAR** ppszDest, long* pcchDest, long* plDestLen)
  600. {
  601.     ASSERT_THIS;
  602.     IMLStrAttrAStr* pAttr;
  603.     HRESULT hr = GetAttrAStr(&pAttr);
  604.     if (SUCCEEDED(hr))
  605.         hr = pAttr->LockAStr(lSrcPos, lSrcLen, lFlags, uCodePageIn, cchRequest, puCodePageOut, ppszDest, pcchDest, plDestLen);
  606.     return hr;
  607. }
  608. STDMETHODIMP CMLStrA::UnlockAStr(const CHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  609. {
  610.     ASSERT_THIS;
  611.     IMLStrAttrAStr* pAttr;
  612.     HRESULT hr = GetAttrAStr(&pAttr);
  613.     if (SUCCEEDED(hr))
  614.         hr = pAttr->UnlockAStr(pszSrc, cchSrc, pcchActual, plActualLen);
  615.     return hr;
  616. }
  617. STDMETHODIMP CMLStrA::SetLocale(long lDestPos, long lDestLen, LCID locale)
  618. {
  619.     ASSERT_THIS;
  620.     IMLStrAttrLocale* pAttr;
  621.     HRESULT hr = GetAttrLocale(&pAttr);
  622.     if (SUCCEEDED(hr))
  623.         hr = pAttr->SetLong(lDestPos, lDestLen, (long)locale);
  624.     return hr;
  625. }
  626. STDMETHODIMP CMLStrA::GetLocale(long lSrcPos, long lSrcMaxLen, LCID* plocale, long* plLocalePos, long* plLocaleLen)
  627. {
  628.     ASSERT_THIS;
  629.     IMLStrAttrLocale* pAttr;
  630.     HRESULT hr = GetAttrLocale(&pAttr);
  631.     if (SUCCEEDED(hr))
  632.         hr = pAttr->GetLong(lSrcPos, lSrcMaxLen, (long*)plocale, plLocalePos, plLocaleLen);
  633.     return hr;
  634. }
  635. #endif NEWMLSTR