624 lines
16 KiB
C++
624 lines
16 KiB
C++
|
// AttrStr.cpp : Implementation of CMLStrAttrStrCommonAttrStrCommon
|
||
|
#include "private.h"
|
||
|
|
||
|
#ifdef NEWMLSTR
|
||
|
|
||
|
#include "attrstr.h"
|
||
|
#include "mlsbwalk.h"
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CMLStrAttrStrCommon
|
||
|
|
||
|
CMLStrAttrStrCommon::CMLStrAttrStrCommon(void) :
|
||
|
m_pMLStrBufW(NULL),
|
||
|
m_pMLStrBufA(NULL),
|
||
|
m_lBufFlags(0),
|
||
|
m_cchBuf(0),
|
||
|
m_locale(0),
|
||
|
m_LockInfo(this)
|
||
|
{
|
||
|
m_dwThreadID = ::GetCurrentThreadId();
|
||
|
}
|
||
|
|
||
|
CMLStrAttrStrCommon::~CMLStrAttrStrCommon(void)
|
||
|
{
|
||
|
if (m_pMLStrBufW)
|
||
|
m_pMLStrBufW->Release();
|
||
|
if (m_pMLStrBufA)
|
||
|
m_pMLStrBufA->Release();
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::SetStrBufCommon(void* pMLStrX, long lDestPos, long lDestLen, UINT uCodePage, IMLangStringBufW* pSrcBufW, IMLangStringBufA* pSrcBufA, long* pcchActual, long* plActualLen)
|
||
|
{
|
||
|
ASSERT_THIS;
|
||
|
ASSERT_READ_PTR_OR_NULL(pSrcBufW);
|
||
|
ASSERT_READ_PTR_OR_NULL(pSrcBufA);
|
||
|
ASSERT(!pSrcBufW || !pSrcBufA); // Either one or both should be NULL
|
||
|
ASSERT_WRITE_PTR_OR_NULL(pcchActual);
|
||
|
ASSERT_WRITE_PTR_OR_NULL(plActualLen);
|
||
|
|
||
|
HRESULT hr = CheckThread();
|
||
|
CLock Lock(TRUE, this, hr);
|
||
|
long lBufFlags = 0; // '= 0' for in case of both of pSrcBufW and pSrcBufA are NULL
|
||
|
long cchBuf = 0;
|
||
|
long cchDestPos;
|
||
|
long cchDestLen;
|
||
|
long lActualLen = 0;
|
||
|
|
||
|
if (SUCCEEDED(hr) &&
|
||
|
(!pSrcBufW || SUCCEEDED(hr = pSrcBufW->GetStatus(&lBufFlags, &cchBuf))) &&
|
||
|
(!pSrcBufA || SUCCEEDED(hr = pSrcBufA->GetStatus(&lBufFlags, &cchBuf))) &&
|
||
|
SUCCEEDED(hr = RegularizePosLen(&lDestPos, &lDestLen)) &&
|
||
|
SUCCEEDED(hr = GetCCh(0, lDestPos, &cchDestPos)) &&
|
||
|
SUCCEEDED(hr = GetCCh(cchDestPos, lDestLen, &cchDestLen)))
|
||
|
{
|
||
|
if (!cchDestPos && cchDestLen == GetBufCCh()) // Replacing entire string
|
||
|
{
|
||
|
IMLangStringBufW* const pOldBufW = GetMLStrBufW();
|
||
|
IMLangStringBufA* const pOldBufA = GetMLStrBufA();
|
||
|
|
||
|
if (pOldBufW)
|
||
|
pOldBufW->Release();
|
||
|
else if (pOldBufA)
|
||
|
pOldBufA->Release();
|
||
|
|
||
|
if (pSrcBufW)
|
||
|
pSrcBufW->AddRef();
|
||
|
else if (pSrcBufA)
|
||
|
pSrcBufA->AddRef();
|
||
|
|
||
|
SetMLStrBufW(pSrcBufW);
|
||
|
SetMLStrBufA(pSrcBufA);
|
||
|
SetCodePage(uCodePage);
|
||
|
SetBufFlags(lBufFlags);
|
||
|
SetBufCCh(cchBuf);
|
||
|
|
||
|
if (plActualLen)
|
||
|
hr = GetLen(0, GetBufCCh(), &lActualLen);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pSrcBufW)
|
||
|
{
|
||
|
CMLStrBufWalkW BufWalk(pSrcBufW, 0, cchBuf, (pcchActual || plActualLen));
|
||
|
|
||
|
while (BufWalk.Lock(hr))
|
||
|
{
|
||
|
long cchSet;
|
||
|
long lSetLen;
|
||
|
|
||
|
hr = ((IMLangStringWStr*)pMLStrX)->SetWStr(lDestPos, lDestLen, BufWalk.GetStr(), BufWalk.GetCCh(), &cchSet, (plActualLen) ? &lSetLen : NULL);
|
||
|
lActualLen += lSetLen;
|
||
|
BufWalk.Unlock(hr, cchSet);
|
||
|
}
|
||
|
|
||
|
cchBuf = BufWalk.GetDoneCCh();
|
||
|
|
||
|
pSrcBufW->Release();
|
||
|
}
|
||
|
else if (pSrcBufA && pMLStrX)
|
||
|
{
|
||
|
CMLStrBufWalkA BufWalk(pSrcBufA, 0, cchBuf, (pcchActual || plActualLen));
|
||
|
|
||
|
while (BufWalk.Lock(hr))
|
||
|
{
|
||
|
long cchSet;
|
||
|
long lSetLen;
|
||
|
|
||
|
hr = ((IMLangStringAStr*)pMLStrX)->SetAStr(lDestPos, lDestLen, uCodePage, BufWalk.GetStr(), BufWalk.GetCCh(), &cchSet, (plActualLen) ? &lSetLen : NULL);
|
||
|
lActualLen += lSetLen;
|
||
|
BufWalk.Unlock(hr, cchSet);
|
||
|
}
|
||
|
|
||
|
cchBuf = BufWalk.GetDoneCCh();
|
||
|
|
||
|
pSrcBufA->Release();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetMLStrAttr()->SetMLStr(lDestPos, lDestLen, NULL, 0, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (pcchActual)
|
||
|
*pcchActual = cchBuf;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = lActualLen;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pcchActual)
|
||
|
*pcchActual = 0;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = 0;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::UnlockWStrDirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
IMLangStringBufW* const pMLStrBufW = GetMLStrBufW();
|
||
|
const long cchLockLen = GetLockInfo()->GetCChLen(pKey);
|
||
|
|
||
|
if (SUCCEEDED(hr = pMLStrBufW->UnlockBuf((WCHAR*)pszSrc, 0, cchSrc)) &&
|
||
|
(GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE))
|
||
|
{
|
||
|
if (cchSrc < cchLockLen)
|
||
|
{
|
||
|
if (SUCCEEDED(hr = pMLStrBufW->Delete(GetLockInfo()->GetCChPos(pKey) + cchSrc, cchLockLen - cchSrc)))
|
||
|
SetBufCCh(GetBufCCh() - (cchLockLen - cchSrc));
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr) && plActualLen)
|
||
|
hr = CalcLenW((WCHAR*)pszSrc, cchSrc, plActualLen);
|
||
|
|
||
|
if (pcchActual)
|
||
|
*pcchActual = cchSrc;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::UnlockWStrIndirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE)
|
||
|
{
|
||
|
CComQIPtr<IMLStrAttrWStr, &IID_IMLStrAttrWStr> pAttrWStr(GetMLStrAttr());
|
||
|
ASSERT(pAttrWStr);
|
||
|
hr = pAttrWStr->SetWStr(GetLockInfo()->GetPos(pKey), GetLockInfo()->GetLen(pKey), (WCHAR*)pszSrc, cchSrc, pcchActual, plActualLen);
|
||
|
}
|
||
|
|
||
|
ASSIGN_IF_FAILED(hr, MemFree((void*)pszSrc));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::UnlockAStrDirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
IMLangStringBufA* const pMLStrBufA = GetMLStrBufA();
|
||
|
const long cchLockLen = GetLockInfo()->GetCChLen(pKey);
|
||
|
|
||
|
if (SUCCEEDED(hr = pMLStrBufA->UnlockBuf((CHAR*)pszSrc, 0, cchSrc)) &&
|
||
|
(GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE))
|
||
|
{
|
||
|
if (cchSrc < cchLockLen)
|
||
|
{
|
||
|
if (SUCCEEDED(hr = pMLStrBufA->Delete(GetLockInfo()->GetCChPos(pKey) + cchSrc, cchLockLen - cchSrc)))
|
||
|
SetBufCCh(GetBufCCh() - (cchLockLen - cchSrc));
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr) && plActualLen)
|
||
|
hr = CalcLenA(GetCodePage(), (CHAR*)pszSrc, cchSrc, plActualLen);
|
||
|
|
||
|
if (pcchActual)
|
||
|
*pcchActual = cchSrc;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::UnlockAStrIndirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE)
|
||
|
{
|
||
|
CComQIPtr<IMLStrAttrAStr, &IID_IMLStrAttrAStr> pAttrAStr(GetMLStrAttr());
|
||
|
ASSERT(pAttrAStr);
|
||
|
hr = pAttrAStr->SetAStr(GetLockInfo()->GetPos(pKey), GetLockInfo()->GetLen(pKey), GetLockInfo()->GetCodePage(pKey), (CHAR*)pszSrc, cchSrc, pcchActual, plActualLen);
|
||
|
}
|
||
|
|
||
|
ASSIGN_IF_FAILED(hr, MemFree((void*)pszSrc));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::UnlockStrCommon(const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
|
||
|
{
|
||
|
HRESULT hr = CheckThread();
|
||
|
void* pLockKey;
|
||
|
long lSrcLen;
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
hr = GetLockInfo()->Find(pszSrc, cchSrc, &pLockKey);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
hr = GetLockInfo()->Unlock(pLockKey, pszSrc, cchSrc, (pcchActual) ? &cchSrc : NULL, (plActualLen) ? &lSrcLen : NULL);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (pcchActual)
|
||
|
*pcchActual = cchSrc;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = lSrcLen;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pcchActual)
|
||
|
*pcchActual = 0;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = 0;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::PrepareMLStrBuf(void)
|
||
|
{
|
||
|
if (GetMLStrBufW() || GetMLStrBufA())
|
||
|
return S_OK;
|
||
|
|
||
|
IMLangStringBufW* pBuf = new CMLStrAttrStrCommon::CMLStrBufStandardW;
|
||
|
if (pBuf)
|
||
|
{
|
||
|
SetMLStrBufW(pBuf);
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::RegularizePosLen(long* plPos, long* plLen)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
long lStrLen;
|
||
|
|
||
|
if (SUCCEEDED(hr = GetLen(0, GetBufCCh(), &lStrLen)))
|
||
|
hr = ::RegularizePosLen(lStrLen, plPos, plLen);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::GetCCh(long cchOffset, long lLen, long* pcchLen)
|
||
|
{
|
||
|
if (GetMLStrBufW())
|
||
|
{
|
||
|
if (pcchLen)
|
||
|
*pcchLen = lLen; // The number of characters is equal to the length
|
||
|
return S_OK;
|
||
|
}
|
||
|
else if (GetMLStrBufA())
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
CMLStrBufWalkA BufWalk(GetMLStrBufA(), cchOffset, GetBufCCh() - cchOffset);
|
||
|
|
||
|
while (lLen > 0 && BufWalk.Lock(hr))
|
||
|
{
|
||
|
for (LPCSTR pszTemp = BufWalk.GetStr(); lLen > 0 && *pszTemp; lLen--)
|
||
|
pszTemp = ::CharNextExA((WORD)GetCodePage(), pszTemp, 0);
|
||
|
|
||
|
if (!*pszTemp)
|
||
|
lLen = 0; // String terminated
|
||
|
|
||
|
BufWalk.Unlock(hr);
|
||
|
}
|
||
|
|
||
|
if (pcchLen)
|
||
|
{
|
||
|
if (SUCCEEDED(hr))
|
||
|
*pcchLen = BufWalk.GetDoneCCh();
|
||
|
else
|
||
|
*pcchLen = 0;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pcchLen)
|
||
|
*pcchLen = 0; // No string
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::GetLen(long cchOffset, long cchLen, long* plLen)
|
||
|
{
|
||
|
if (GetMLStrBufW())
|
||
|
{
|
||
|
if (plLen)
|
||
|
*plLen = cchLen; // The length is equal to the number of characters
|
||
|
return S_OK;
|
||
|
}
|
||
|
else if (GetMLStrBufA())
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
long lDoneLen = 0;
|
||
|
CMLStrBufWalkA BufWalk(GetMLStrBufA(), cchOffset, cchLen);
|
||
|
|
||
|
while (BufWalk.Lock(hr))
|
||
|
{
|
||
|
long lTempLen;
|
||
|
|
||
|
hr = CalcLenA(GetCodePage(), BufWalk.GetStr(), BufWalk.GetCCh(), &lTempLen);
|
||
|
if (hr == S_FALSE)
|
||
|
cchLen = 0; // String terminated
|
||
|
lDoneLen += lTempLen;
|
||
|
|
||
|
BufWalk.Unlock(hr);
|
||
|
}
|
||
|
|
||
|
if (plLen)
|
||
|
{
|
||
|
if (SUCCEEDED(hr))
|
||
|
*plLen = lDoneLen;
|
||
|
else
|
||
|
*plLen = 0;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (plLen)
|
||
|
*plLen = 0; // No string
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::CalcLenA(UINT uCodePage, const CHAR* psz, long cchLen, long* plLen)
|
||
|
{
|
||
|
long lLen = 0;
|
||
|
const CHAR* const pszEnd = psz + cchLen;
|
||
|
|
||
|
for (; psz < pszEnd && *psz; lLen++)
|
||
|
{
|
||
|
const CHAR* const pszNew = ::CharNextExA((WORD)uCodePage, psz, 0);
|
||
|
|
||
|
if (pszNew > pszEnd) // Overrun out of buffer
|
||
|
break;
|
||
|
|
||
|
psz = pszNew;
|
||
|
}
|
||
|
|
||
|
if (plLen)
|
||
|
*plLen = lLen;
|
||
|
|
||
|
if (*psz)
|
||
|
return S_OK;
|
||
|
else
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::CalcCChA(UINT uCodePage, const CHAR* psz, long lLen, long* pcchLen)
|
||
|
{
|
||
|
const CHAR* const pszStart = psz;
|
||
|
|
||
|
for (; lLen > 0 && *psz; lLen--)
|
||
|
psz = ::CharNextExA((WORD)uCodePage, psz, 0);
|
||
|
|
||
|
if (pcchLen)
|
||
|
*pcchLen = psz - pszStart;
|
||
|
|
||
|
if (*psz)
|
||
|
return S_OK;
|
||
|
else
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::ConvAStrToWStr(UINT uCodePage, const CHAR* pszSrc, long cchSrc, WCHAR* pszDest, long cchDest, long* pcchActualA, long* pcchActualW, long* plActualLen)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
long lWrittenLen;
|
||
|
long cchWrittenA;
|
||
|
|
||
|
long cchWrittenW = ::MultiByteToWideChar(uCodePage, 0, pszSrc, cchSrc, pszDest, (pszDest) ? cchDest : 0);
|
||
|
if (!cchWrittenW)
|
||
|
hr = E_FAIL; // NLS failed
|
||
|
|
||
|
if ((pcchActualA || plActualLen) && SUCCEEDED(hr))
|
||
|
hr = CalcLenW(pszDest, cchWrittenW, &lWrittenLen); // BOGUS: pszDest may be NULL
|
||
|
|
||
|
if (pcchActualA && SUCCEEDED(hr))
|
||
|
hr = CalcCChA(uCodePage, pszSrc, lWrittenLen, &cchWrittenA);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (pcchActualA)
|
||
|
*pcchActualA = cchWrittenA;
|
||
|
if (pcchActualW)
|
||
|
*pcchActualW = cchWrittenW;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = lWrittenLen;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pcchActualA)
|
||
|
*pcchActualA = 0;
|
||
|
if (pcchActualW)
|
||
|
*pcchActualW = 0;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = 0;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::ConvWStrToAStr(BOOL fCanStopAtMiddle, UINT uCodePage, const WCHAR* pszSrc, long cchSrc, CHAR* pszDest, long cchDest, long* pcchActualA, long* pcchActualW, long* plActualLen)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
long lWrittenLen;
|
||
|
long cchWrittenW;
|
||
|
|
||
|
long cchWrittenA = ::WideCharToMultiByte(uCodePage, (fCanStopAtMiddle) ? 0 : WC_DEFAULTCHAR, pszSrc, cchSrc, pszDest, (pszDest) ? cchDest : 0, NULL, NULL);
|
||
|
if (!cchWrittenA)
|
||
|
hr = E_FAIL; // NLS failed
|
||
|
|
||
|
if ((pcchActualW || plActualLen) && SUCCEEDED(hr))
|
||
|
{
|
||
|
if (pszDest)
|
||
|
hr = CalcLenA(uCodePage, pszDest, cchWrittenA, &lWrittenLen);
|
||
|
else
|
||
|
hr = E_NOTIMPL; // Can't retrieve pcchActualW and plActualLen
|
||
|
}
|
||
|
|
||
|
if (pcchActualW && SUCCEEDED(hr))
|
||
|
hr = CalcCChW(pszSrc, lWrittenLen, &cchWrittenW);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (pcchActualA)
|
||
|
*pcchActualA = cchWrittenA;
|
||
|
if (pcchActualW)
|
||
|
*pcchActualW = cchWrittenW;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = lWrittenLen;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pcchActualA)
|
||
|
*pcchActualA = 0;
|
||
|
if (pcchActualW)
|
||
|
*pcchActualW = 0;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = 0;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CMLStrAttrStrCommon::CLockInfo
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::CLockInfo::UnlockAll(void)
|
||
|
{
|
||
|
if (m_pLockArray)
|
||
|
{
|
||
|
for (int n = 0; n < MAX_LOCK_COUNT; n++)
|
||
|
{
|
||
|
if (m_pLockArray[n].m_psz)
|
||
|
Unlock(&m_pLockArray[n], m_pLockArray[n].m_psz, m_pLockArray[n].m_cchLen, NULL, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::CLockInfo::Lock(PFNUNLOCKPROC pfnUnlockProc, long lFlags, UINT uCodePage, void* psz, long lPos, long lLen, long cchPos, long cchLen)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
int nIndex;
|
||
|
|
||
|
if (!m_pLockArray)
|
||
|
{
|
||
|
m_pLockArray = new CLockInfoEntry[MAX_LOCK_COUNT];
|
||
|
|
||
|
if (m_pLockArray)
|
||
|
{
|
||
|
for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++)
|
||
|
m_pLockArray[nIndex].m_psz = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++)
|
||
|
{
|
||
|
if (!m_pLockArray[nIndex].m_psz)
|
||
|
break;
|
||
|
}
|
||
|
if (nIndex >= MAX_LOCK_COUNT)
|
||
|
hr = MLSTR_E_TOOMANYNESTOFLOCK;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
m_pLockArray[nIndex].m_psz = psz;
|
||
|
m_pLockArray[nIndex].m_pfnUnlockProc = pfnUnlockProc;
|
||
|
m_pLockArray[nIndex].m_lFlags = lFlags;
|
||
|
m_pLockArray[nIndex].m_uCodePage = uCodePage;
|
||
|
m_pLockArray[nIndex].m_lPos = lPos;
|
||
|
m_pLockArray[nIndex].m_lLen = lLen;
|
||
|
m_pLockArray[nIndex].m_cchPos = cchPos;
|
||
|
m_pLockArray[nIndex].m_cchLen = cchLen;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::CLockInfo::Find(const void* psz, long, void** ppKey)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
int nIndex;
|
||
|
|
||
|
if (m_pLockArray)
|
||
|
{
|
||
|
for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++)
|
||
|
{
|
||
|
if (psz == m_pLockArray[nIndex].m_psz)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!m_pLockArray || nIndex >= MAX_LOCK_COUNT)
|
||
|
hr = E_INVALIDARG;
|
||
|
|
||
|
if (ppKey)
|
||
|
{
|
||
|
if (SUCCEEDED(hr))
|
||
|
*ppKey = &m_pLockArray[nIndex];
|
||
|
else
|
||
|
*ppKey = NULL;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMLStrAttrStrCommon::CLockInfo::Unlock(void* pKey, const void* psz, long cch, long* pcchActual, long* plActualLen)
|
||
|
{
|
||
|
CLockInfoEntry* const pEntry = (CLockInfoEntry*)pKey;
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (!(pEntry->m_lFlags & MLSTR_WRITE))
|
||
|
{
|
||
|
cch = 0;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = 0;
|
||
|
}
|
||
|
|
||
|
hr = (m_pCommon->*(pEntry->m_pfnUnlockProc))(pKey, psz, cch, pcchActual, plActualLen);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
hr = EndLock(pEntry->m_lFlags & MLSTR_WRITE);
|
||
|
|
||
|
pEntry->m_psz = NULL; // Remove from lock array anyway
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
if (pcchActual)
|
||
|
*pcchActual = 0;
|
||
|
if (plActualLen)
|
||
|
*plActualLen = 0;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CMLStrAttrStrCommon::CMLStrBufStandardW
|
||
|
|
||
|
long CMLStrAttrStrCommon::CMLStrBufStandardW::RoundBufSize(long cchStr)
|
||
|
{
|
||
|
for (int n = 8; n < 12; n++)
|
||
|
{
|
||
|
if (cchStr < (1L << n))
|
||
|
break;
|
||
|
}
|
||
|
const long cchTick = (1L << (n - 4));
|
||
|
return (cchStr + cchTick - 1) / cchTick * cchTick;
|
||
|
}
|
||
|
|
||
|
#endif // NEWMLSTR
|