// MLStrW.cpp : Implementation of CMLStrW #include "private.h" #ifndef NEWMLSTR #ifdef ASTRIMPL #include "mlstr.h" #include "mlsbwalk.h" ///////////////////////////////////////////////////////////////////////////// // CMLStrW STDMETHODIMP CMLStrW::Sync(BOOL fNoAccess) { ASSERT_THIS; return GetOwner()->Sync(fNoAccess); } STDMETHODIMP CMLStrW::GetLength(long* plLen) { ASSERT_THIS; return GetOwner()->GetLength(plLen); } STDMETHODIMP CMLStrW::SetMLStr(long lDestPos, long lDestLen, IUnknown* pSrcMLStr, long lSrcPos, long lSrcLen) { ASSERT_THIS; return GetOwner()->SetMLStr(lDestPos, lDestLen, pSrcMLStr, lSrcPos, lSrcLen); } STDMETHODIMP CMLStrW::GetMLStr(long lSrcPos, long lSrcLen, IUnknown* pUnkOuter, DWORD dwClsContext, const IID* piid, IUnknown** ppDestMLStr, long* plDestPos, long* plDestLen) { ASSERT_THIS; return GetOwner()->GetMLStr(lSrcPos, lSrcLen, pUnkOuter, dwClsContext, piid, ppDestMLStr, plDestPos, plDestLen); } STDMETHODIMP CMLStrW::SetWStr(long lDestPos, long lDestLen, const WCHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { ASSERT_THIS; ASSERT_READ_BLOCK(pszSrc, cchSrc); ASSERT_WRITE_PTR_OR_NULL(pcchActual); ASSERT_WRITE_PTR_OR_NULL(plActualLen); POWNER const pOwner = GetOwner(); HRESULT hr = pOwner->CheckThread(); CMLStr::CLock Lock(TRUE, pOwner, hr); long cchDestPos; long cchDestLen; long cchActual; long lActualLen; if (SUCCEEDED(hr) && (pOwner->GetBufFlags() & MLSTR_WRITE)) hr = E_INVALIDARG; // Not writable StrBuf; TODO: Replace StrBuf in this case if allowed if (SUCCEEDED(hr) && SUCCEEDED(hr = pOwner->PrepareMLStrBuf()) && SUCCEEDED(hr = pOwner->RegularizePosLen(&lDestPos, &lDestLen)) && SUCCEEDED(hr = pOwner->GetCCh(0, lDestPos, &cchDestPos)) && SUCCEEDED(hr = pOwner->GetCCh(cchDestPos, lDestLen, &cchDestLen))) { IMLangStringBufW* const pMLStrBufW = pOwner->GetMLStrBufW(); if (pMLStrBufW) { if (cchSrc > cchDestLen) { hr = pMLStrBufW->Insert(cchDestPos, cchSrc - cchDestLen, (pcchActual || plActualLen) ? &cchSrc : NULL); cchSrc += cchDestLen; } else if (cchSrc < cchDestLen) { hr = pMLStrBufW->Delete(cchDestPos, cchDestLen - cchSrc); } CMLStrBufWalkW BufWalk(pMLStrBufW, cchDestPos, cchSrc, (pcchActual || plActualLen)); lActualLen = 0; while (BufWalk.Lock(hr)) { long lLen; if (plActualLen) hr = pOwner->CalcLenW(pszSrc, BufWalk.GetCCh(), &lLen); if (SUCCEEDED(hr)) { lActualLen += lLen; ::memcpy(BufWalk.GetStr(), pszSrc, sizeof(WCHAR) * BufWalk.GetCCh()); pszSrc += BufWalk.GetCCh(); } BufWalk.Unlock(hr); } cchActual = BufWalk.GetDoneCCh(); } else { IMLangStringBufA* const pMLStrBufA = pOwner->GetMLStrBufA(); // Should succeed because PrepareMLStrBuf() above was succeeded const UINT uCodePage = pOwner->GetCodePage(); long cchSrcA; if (SUCCEEDED(hr = pOwner->ConvWStrToAStr(pcchActual || plActualLen, uCodePage, pszSrc, cchSrc, NULL, 0, &cchSrcA, NULL, NULL))) { if (cchSrcA > cchDestLen) { hr = pMLStrBufA->Insert(cchDestPos, cchSrcA - cchDestLen, (pcchActual || plActualLen) ? &cchSrcA : NULL); cchSrcA += cchDestLen; } else if (cchSrcA < cchDestLen) { hr = pMLStrBufA->Delete(cchDestPos, cchDestLen - cchSrcA); } } CMLStrBufWalkA BufWalk(pMLStrBufA, cchDestPos, cchSrcA, (pcchActual || plActualLen)); cchActual = 0; lActualLen = 0; while (BufWalk.Lock(hr)) { long cchWrittenA; long cchWrittenW; long lWrittenLen; if (SUCCEEDED(hr = pOwner->ConvWStrToAStr(pcchActual || plActualLen, uCodePage, pszSrc, cchSrc, BufWalk.GetStr(), BufWalk.GetCCh(), &cchWrittenA, &cchWrittenW, &lWrittenLen))) { pszSrc += cchWrittenW; cchSrc -= cchWrittenW; cchActual += cchWrittenW; lActualLen += lWrittenLen; } BufWalk.Unlock(hr, cchWrittenA); } } } if (SUCCEEDED(hr)) { if (pcchActual) *pcchActual = cchActual; if (plActualLen) *plActualLen = lActualLen; } else { if (pcchActual) *pcchActual = 0; if (plActualLen) *plActualLen = 0; } return hr; } STDMETHODIMP CMLStrW::SetStrBufW(long lDestPos, long lDestLen, IMLangStringBufW* pSrcBuf, long* pcchActual, long* plActualLen) { ASSERT_THIS; return GetOwner()->SetStrBufCommon(this, lDestPos, lDestLen, 0, pSrcBuf, NULL, pcchActual, plActualLen); } STDMETHODIMP CMLStrW::GetWStr(long lSrcPos, long lSrcLen, WCHAR* pszDest, long cchDest, long* pcchActual, long* plActualLen) { ASSERT_THIS; ASSERT_WRITE_BLOCK_OR_NULL(pszDest, cchDest); ASSERT_WRITE_PTR_OR_NULL(pcchActual); ASSERT_WRITE_PTR_OR_NULL(plActualLen); POWNER const pOwner = GetOwner(); HRESULT hr = pOwner->CheckThread(); CMLStr::CLock Lock(FALSE, pOwner, hr); long cchSrcPos; long cchSrcLen; long cchActual; long lActualLen; if (SUCCEEDED(hr) && SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcLen)) && SUCCEEDED(hr = pOwner->GetCCh(0, lSrcPos, &cchSrcPos)) && SUCCEEDED(hr = pOwner->GetCCh(cchSrcPos, lSrcLen, &cchSrcLen))) { IMLangStringBufW* const pMLStrBufW = pOwner->GetMLStrBufW(); IMLangStringBufA* const pMLStrBufA = pOwner->GetMLStrBufA(); if (pszDest) cchActual = min(cchSrcLen, cchDest); else cchActual = cchSrcLen; if (pMLStrBufW) { CMLStrBufWalkW BufWalk(pMLStrBufW, cchSrcPos, cchActual, (pcchActual || plActualLen)); lActualLen = 0; while (BufWalk.Lock(hr)) { long lLen; if (plActualLen) hr = pOwner->CalcLenW(BufWalk.GetStr(), BufWalk.GetCCh(), &lLen); if (SUCCEEDED(hr)) { lActualLen += lLen; if (pszDest) { ::memcpy(pszDest, BufWalk.GetStr(), sizeof(WCHAR) * BufWalk.GetCCh()); pszDest += BufWalk.GetCCh(); } } BufWalk.Unlock(hr); } cchActual = BufWalk.GetDoneCCh(); } else if (pMLStrBufA) { CMLStrBufWalkA BufWalk(pMLStrBufA, cchSrcPos, cchActual, (pcchActual || plActualLen)); cchActual = 0; lActualLen = 0; while ((!pszDest || cchDest > 0) && BufWalk.Lock(hr)) { CHAR* const pszBuf = BufWalk.GetStr(); long cchWrittenA; long cchWrittenW; long lWrittenLen; if (SUCCEEDED(hr = pOwner->ConvAStrToWStr(pOwner->GetCodePage(), pszBuf, BufWalk.GetCCh(), pszDest, cchDest, &cchWrittenA, &cchWrittenW, &lWrittenLen))) { lActualLen += lWrittenLen; cchActual += cchWrittenW; if (pszDest) { pszDest += cchWrittenW; cchDest -= cchWrittenW; } } BufWalk.Unlock(hr, cchWrittenA); } } else { ASSERT(cchActual == 0); // MLStrBuf is not available lActualLen = 0; } } if (SUCCEEDED(hr)) { if (pcchActual) *pcchActual = cchActual; if (plActualLen) *plActualLen = lActualLen; } else { if (pcchActual) *pcchActual = 0; if (plActualLen) *plActualLen = 0; } return hr; } STDMETHODIMP CMLStrW::GetStrBufW(long lSrcPos, long lSrcMaxLen, IMLangStringBufW** ppDestBuf, long* plDestLen) { ASSERT_THIS; ASSERT_WRITE_PTR_OR_NULL(ppDestBuf); ASSERT_WRITE_PTR_OR_NULL(plDestLen); POWNER const pOwner = GetOwner(); HRESULT hr = pOwner->CheckThread(); CMLStr::CLock Lock(FALSE, pOwner, hr); IMLangStringBufW* pMLStrBufW; if (SUCCEEDED(hr) && SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcMaxLen)) && lSrcMaxLen <= 0) { hr = E_INVALIDARG; } if (SUCCEEDED(hr)) { pMLStrBufW = pOwner->GetMLStrBufW(); if (!pMLStrBufW) hr = MLSTR_E_STRBUFNOTAVAILABLE; } if (SUCCEEDED(hr)) { if (ppDestBuf) { pMLStrBufW->AddRef(); *ppDestBuf = pMLStrBufW; } if (plDestLen) *plDestLen = lSrcMaxLen; } else { if (ppDestBuf) *ppDestBuf = NULL; if (plDestLen) *plDestLen = 0; } return hr; } STDMETHODIMP CMLStrW::LockWStr(long lSrcPos, long lSrcLen, long lFlags, long cchRequest, WCHAR** ppszDest, long* pcchDest, long* plDestLen) { ASSERT_THIS; ASSERT_WRITE_PTR_OR_NULL(ppszDest); ASSERT_WRITE_PTR_OR_NULL(pcchDest); ASSERT_WRITE_PTR_OR_NULL(plDestLen); POWNER const pOwner = GetOwner(); HRESULT hr = pOwner->CheckThread(); CMLStr::CLock Lock(lFlags & MLSTR_WRITE, pOwner, hr); long cchSrcPos; long cchSrcLen; WCHAR* pszBuf = NULL; long cchBuf; long lLockLen; BOOL fDirectLock; if (SUCCEEDED(hr) && (!lFlags || (lFlags & ~pOwner->GetBufFlags() & MLSTR_WRITE))) hr = E_INVALIDARG; // No flags specified, or not writable StrBuf; TODO: Replace StrBuf in this case if allowed if (!(lFlags & MLSTR_WRITE)) cchRequest = 0; if (SUCCEEDED(hr) && SUCCEEDED(hr = pOwner->PrepareMLStrBuf()) && SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcLen)) && SUCCEEDED(hr = pOwner->GetCCh(0, lSrcPos, &cchSrcPos)) && SUCCEEDED(hr = pOwner->GetCCh(cchSrcPos, lSrcLen, &cchSrcLen))) { IMLangStringBufW* const pMLStrBufW = pOwner->GetMLStrBufW(); fDirectLock = (pMLStrBufW != 0); if (fDirectLock) { long cchInserted; long cchLockLen = cchSrcLen; if (cchRequest > cchSrcLen && SUCCEEDED(hr = pMLStrBufW->Insert(cchSrcPos + cchSrcLen, cchRequest - cchSrcLen, &cchInserted))) { pOwner->SetBufCCh(pOwner->GetBufCCh() + cchInserted); cchLockLen += cchInserted; if (!pcchDest && cchLockLen < cchRequest) hr = E_OUTOFMEMORY; // Can't insert in StrBuf } if (SUCCEEDED(hr) && SUCCEEDED(hr = pMLStrBufW->LockBuf(cchSrcPos, cchLockLen, &pszBuf, &cchBuf)) && !pcchDest && cchBuf < max(cchSrcLen, cchRequest)) { hr = E_OUTOFMEMORY; // Can't lock StrBuf } if (plDestLen && SUCCEEDED(hr)) hr = pOwner->CalcLenW(pszBuf, cchBuf, &lLockLen); } else { long cchSize; if (SUCCEEDED(hr = pOwner->CalcBufSizeW(lSrcLen, &cchSize))) { cchBuf = max(cchSize, cchRequest); hr = pOwner->MemAlloc(sizeof(*pszBuf) * cchBuf, (void**)&pszBuf); } if (SUCCEEDED(hr) && (lFlags & MLSTR_READ)) hr = GetWStr(lSrcPos, lSrcLen, pszBuf, cchBuf, (pcchDest) ? &cchBuf : NULL, (plDestLen) ? &lLockLen : NULL); } } if (SUCCEEDED(hr) && SUCCEEDED(hr = Lock.FallThrough())) { hr = pOwner->GetLockInfo()->Lock((fDirectLock) ? pOwner->UnlockWStrDirect : pOwner->UnlockWStrIndirect, lFlags, 0, pszBuf, lSrcPos, lSrcLen, cchSrcPos, cchBuf); } if (SUCCEEDED(hr)) { if (ppszDest) *ppszDest = pszBuf; if (pcchDest) *pcchDest = cchBuf; if (plDestLen) *plDestLen = lLockLen; } else { if (pszBuf) { if (fDirectLock) pOwner->GetMLStrBufW()->UnlockBuf(pszBuf, 0, 0); else pOwner->MemFree(pszBuf); } if (ppszDest) *ppszDest = NULL; if (pcchDest) *pcchDest = 0; if (plDestLen) *plDestLen = 0; } return hr; } STDMETHODIMP CMLStrW::UnlockWStr(const WCHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { ASSERT_THIS; ASSERT_READ_BLOCK(pszSrc, cchSrc); ASSERT_WRITE_PTR_OR_NULL(pcchActual); ASSERT_WRITE_PTR_OR_NULL(plActualLen); return GetOwner()->UnlockStrCommon(pszSrc, cchSrc, pcchActual, plActualLen); } STDMETHODIMP CMLStrW::SetLocale(long lDestPos, long lDestLen, LCID locale) { ASSERT_THIS; return GetOwner()->SetLocale(lDestPos, lDestLen, locale); } STDMETHODIMP CMLStrW::GetLocale(long lSrcPos, long lSrcMaxLen, LCID* plocale, long* plLocalePos, long* plLocaleLen) { ASSERT_THIS; return GetOwner()->GetLocale(lSrcPos, lSrcMaxLen, plocale, plLocalePos, plLocaleLen); } #endif #else // NEWMLSTR #include "mlstr.h" ///////////////////////////////////////////////////////////////////////////// // CMLStrW CMLStrW::CMLStrW(void) : m_pAttrWStr(NULL), m_pAttrLocale(NULL), m_dwAttrWStrCookie(NULL), m_dwAttrLocaleCookie(NULL) { DllAddRef(); ::InitializeCriticalSection(&m_cs); } CMLStrW::~CMLStrW(void) { if (m_dwAttrLocaleCookie) GetOwner()->UnregisterAttr(m_dwAttrLocaleCookie); if (m_dwAttrWStrCookie) GetOwner()->UnregisterAttr(m_dwAttrWStrCookie); if (m_pAttrLocale) m_pAttrLocale->Release(); if (m_pAttrWStr) m_pAttrWStr->Release(); ::DeleteCriticalSection(&m_cs); DllRelease(); } HRESULT CMLStrW::GetAttrWStrReal(IMLStrAttrWStr** ppAttr) { HRESULT hr = S_OK; ::EnterCriticalSection(&m_cs); if (!m_pAttrWStr) { IMLStrAttrWStr* pAttr; hr = ::CoCreateInstance(CLSID_CMLStrAttrWStr, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pAttr); if (SUCCEEDED(hr)) hr = GetOwner()->RegisterAttr(pAttr, &m_dwAttrWStrCookie); if (SUCCEEDED(hr)) { pAttr->Release(); hr = GetOwner()->FindAttr(IID_IMLStrAttrWStr, 0, (IUnknown**)&pAttr); } if (SUCCEEDED(hr)) m_pAttrWStr = pAttr; } if (ppAttr) *ppAttr = m_pAttrWStr; ::LeaveCriticalSection(&m_cs); return hr; } HRESULT CMLStrW::GetAttrLocaleReal(IMLStrAttrLocale** ppAttr) { HRESULT hr = S_OK; ::EnterCriticalSection(&m_cs); if (!m_pAttrLocale) { IMLStrAttrLocale* pAttr; hr = ::CoCreateInstance(CLSID_CMLStrAttrLocale, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pAttr); if (SUCCEEDED(hr)) hr = GetOwner()->RegisterAttr(pAttr, &m_dwAttrLocaleCookie); if (SUCCEEDED(hr)) { pAttr->Release(); hr = GetOwner()->FindAttr(IID_IMLStrAttrLocale, 0, (IUnknown**)&pAttr); } if (SUCCEEDED(hr)) m_pAttrLocale = pAttr; } if (ppAttr) *ppAttr = m_pAttrLocale; ::LeaveCriticalSection(&m_cs); return hr; } STDMETHODIMP CMLStrW::LockMLStr(long lPos, long lLen, DWORD dwFlags, DWORD* pdwCookie, long* plActualPos, long* plActualLen) { ASSERT_THIS; return GetOwner()->LockMLStr(lPos, lLen, dwFlags, pdwCookie, plActualPos, plActualLen); } STDMETHODIMP CMLStrW::UnlockMLStr(DWORD dwCookie) { ASSERT_THIS; return GetOwner()->UnlockMLStr(dwCookie); } STDMETHODIMP CMLStrW::GetLength(long* plLen) { ASSERT_THIS; return GetOwner()->GetLength(plLen); } STDMETHODIMP CMLStrW::SetMLStr(long lDestPos, long lDestLen, IUnknown* pSrcMLStr, long lSrcPos, long lSrcLen) { ASSERT_THIS; return GetOwner()->SetMLStr(lDestPos, lDestLen, pSrcMLStr, lSrcPos, lSrcLen); } STDMETHODIMP CMLStrW::RegisterAttr(IUnknown* pUnk, DWORD* pdwCookie) { ASSERT_THIS; return GetOwner()->RegisterAttr(pUnk, pdwCookie); } STDMETHODIMP CMLStrW::UnregisterAttr(DWORD dwCookie) { ASSERT_THIS; return GetOwner()->UnregisterAttr(dwCookie); } STDMETHODIMP CMLStrW::EnumAttr(IEnumUnknown** ppEnumUnk) { ASSERT_THIS; return GetOwner()->EnumAttr(ppEnumUnk); } STDMETHODIMP CMLStrW::FindAttr(REFIID riid, LPARAM lParam, IUnknown** ppUnk) { ASSERT_THIS; return GetOwner()->FindAttr(riid, lParam, ppUnk); } STDMETHODIMP CMLStrW::SetWStr(long lDestPos, long lDestLen, const WCHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { ASSERT_THIS; IMLStrAttrWStr* pAttr; HRESULT hr = GetAttrWStr(&pAttr); if (SUCCEEDED(hr)) hr = pAttr->SetWStr(lDestPos, lDestLen, pszSrc, cchSrc, pcchActual, plActualLen); return hr; } STDMETHODIMP CMLStrW::SetStrBufW(long lDestPos, long lDestLen, IMLangStringBufW* pSrcBuf, long* pcchActual, long* plActualLen) { ASSERT_THIS; IMLStrAttrWStr* pAttr; HRESULT hr = GetAttrWStr(&pAttr); if (SUCCEEDED(hr)) hr = pAttr->SetStrBufW(lDestPos, lDestLen, pSrcBuf, pcchActual, plActualLen); return hr; } STDMETHODIMP CMLStrW::GetWStr(long lSrcPos, long lSrcLen, WCHAR* pszDest, long cchDest, long* pcchActual, long* plActualLen) { ASSERT_THIS; IMLStrAttrWStr* pAttr; HRESULT hr = GetAttrWStr(&pAttr); if (SUCCEEDED(hr)) hr = pAttr->GetWStr(lSrcPos, lSrcLen, pszDest, cchDest, pcchActual, plActualLen); return hr; } STDMETHODIMP CMLStrW::GetStrBufW(long lSrcPos, long lSrcMaxLen, IMLangStringBufW** ppDestBuf, long* plDestLen) { ASSERT_THIS; IMLStrAttrWStr* pAttr; HRESULT hr = GetAttrWStr(&pAttr); if (SUCCEEDED(hr)) hr = pAttr->GetStrBufW(lSrcPos, lSrcMaxLen, ppDestBuf, plDestLen); return hr; } STDMETHODIMP CMLStrW::LockWStr(long lSrcPos, long lSrcLen, long lFlags, long cchRequest, WCHAR** ppszDest, long* pcchDest, long* plDestLen) { ASSERT_THIS; IMLStrAttrWStr* pAttr; HRESULT hr = GetAttrWStr(&pAttr); if (SUCCEEDED(hr)) hr = pAttr->LockWStr(lSrcPos, lSrcLen, lFlags, cchRequest, ppszDest, pcchDest, plDestLen); return hr; } STDMETHODIMP CMLStrW::UnlockWStr(const WCHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { ASSERT_THIS; IMLStrAttrWStr* pAttr; HRESULT hr = GetAttrWStr(&pAttr); if (SUCCEEDED(hr)) hr = pAttr->UnlockWStr(pszSrc, cchSrc, pcchActual, plActualLen); return hr; } STDMETHODIMP CMLStrW::SetLocale(long lDestPos, long lDestLen, LCID locale) { ASSERT_THIS; IMLStrAttrLocale* pAttr; HRESULT hr = GetAttrLocale(&pAttr); if (SUCCEEDED(hr)) hr = pAttr->SetLong(lDestPos, lDestLen, (long)locale); return hr; } STDMETHODIMP CMLStrW::GetLocale(long lSrcPos, long lSrcMaxLen, LCID* plocale, long* plLocalePos, long* plLocaleLen) { ASSERT_THIS; IMLStrAttrLocale* pAttr; HRESULT hr = GetAttrLocale(&pAttr); if (SUCCEEDED(hr)) hr = pAttr->GetLong(lSrcPos, lSrcMaxLen, (long*)plocale, plLocalePos, plLocaleLen); return hr; } #endif // NEWMLSTR