windows-nt/Source/XPSP1/NT/shell/ext/mlang/mlsbwalk.h
2020-09-26 16:20:57 +08:00

126 lines
3.1 KiB
C++

// MLSBWalk.h : Declaration of the CMLStrBufWalk
#ifndef __MLSBWALK_H_
#define __MLSBWALK_H_
/////////////////////////////////////////////////////////////////////////////
// CMLStrBufWalk
template <class IMLSTRBUF, class CHTYPE>
class CMLStrBufWalk
{
public:
inline CMLStrBufWalk(IMLSTRBUF* pMLStrBuf, long cchOffset, long cchLen, BOOL fCanStopAtMiddle = FALSE);
BOOL Lock(HRESULT& rhr);
void Unlock(HRESULT& rhr, long cchActual = 0);
inline CHTYPE* GetStr(void);
inline long GetCCh(void) const;
inline long GetDoneCCh(void) const;
inline long GetRestCCh(void) const;
protected:
IMLSTRBUF* m_pMLStrBuf;
BOOL m_fCanStopAtMiddle;
long m_cchOffset;
long m_cchLen;
long m_cchDone;
CHTYPE* m_pszBuf;
long m_cchBuf;
};
template <class IMLSTRBUF, class CHTYPE>
CMLStrBufWalk<IMLSTRBUF, CHTYPE>::CMLStrBufWalk(IMLSTRBUF* pMLStrBuf, long cchOffset, long cchLen, BOOL fCanStopAtMiddle) :
m_pMLStrBuf(pMLStrBuf),
m_fCanStopAtMiddle(fCanStopAtMiddle)
{
m_cchOffset = cchOffset;
m_cchLen = cchLen;
m_cchDone = 0;
m_pszBuf = NULL; // Mark as it's not locked
}
template <class IMLSTRBUF, class CHTYPE>
BOOL CMLStrBufWalk<IMLSTRBUF, CHTYPE>::Lock(HRESULT& rhr)
{
if (m_pszBuf)
rhr = E_FAIL; // Already locked
if (SUCCEEDED(rhr) &&
m_cchLen > 0 &&
FAILED(rhr = m_pMLStrBuf->LockBuf(m_cchOffset, m_cchLen, &m_pszBuf, &m_cchBuf)))
{
m_pszBuf = NULL; // Mark as it's not locked
}
if (m_fCanStopAtMiddle && FAILED(rhr) && m_cchDone > 0)
{
rhr = S_OK;
return FALSE; // Stop it, but not fail
}
else
{
return (SUCCEEDED(rhr) && m_cchLen > 0);
}
}
template <class IMLSTRBUF, class CHTYPE>
void CMLStrBufWalk<IMLSTRBUF, CHTYPE>::Unlock(HRESULT& rhr, long cchActual)
{
HRESULT hr = S_OK;
if (!m_pszBuf)
hr = E_FAIL; // Not locked yet
if (SUCCEEDED(hr) &&
SUCCEEDED(hr = m_pMLStrBuf->UnlockBuf(m_pszBuf, 0, 0))) // Unlock even if rhr is already failed
{
if (!cchActual)
cchActual = m_cchBuf;
else
ASSERT(cchActual > 0 && cchActual <= m_cchBuf);
m_cchOffset += cchActual;
m_cchLen -= cchActual;
m_cchDone += cchActual;
}
m_pszBuf = NULL; // Unlock anyway
if (SUCCEEDED(rhr))
rhr = hr; // if rhr is failed before UnlockBuf, use it
}
template <class IMLSTRBUF, class CHTYPE>
CHTYPE* CMLStrBufWalk<IMLSTRBUF, CHTYPE>::GetStr(void)
{
ASSERT(m_pszBuf); // Not locked
return m_pszBuf;
}
template <class IMLSTRBUF, class CHTYPE>
long CMLStrBufWalk<IMLSTRBUF, CHTYPE>::GetCCh(void) const
{
ASSERT(m_pszBuf); // Not locked
if (m_pszBuf)
return m_cchBuf;
else
return 0;
}
template <class IMLSTRBUF, class CHTYPE>
long CMLStrBufWalk<IMLSTRBUF, CHTYPE>::GetDoneCCh(void) const
{
return m_cchDone;
}
template <class IMLSTRBUF, class CHTYPE>
long CMLStrBufWalk<IMLSTRBUF, CHTYPE>::GetRestCCh(void) const
{
return m_cchLen - m_cchDone;
}
typedef CMLStrBufWalk<IMLangStringBufW, WCHAR> CMLStrBufWalkW;
typedef CMLStrBufWalk<IMLangStringBufA, CHAR> CMLStrBufWalkA;
#endif //__MLSBWALK_H_