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

411 lines
16 KiB
C++

#ifndef NEWMLSTR
// MLStr.h : Declaration of the CMLStr
#ifndef __MLSTR_H_
#define __MLSTR_H_
#ifdef ASTRIMPL
#include "mlstrw.h"
#endif
#include "mlstra.h"
#ifdef ASTRIMPL
#include "mlstrbuf.h"
#endif
#define MAX_LOCK_COUNT 4
// Error Code
#define FACILITY_MLSTR 0x0A15
#define MLSTR_E_ACCESSDENIED MAKE_HRESULT(1, FACILITY_MLSTR, 1002)
#define MLSTR_E_TOOMANYNESTOFLOCK MAKE_HRESULT(1, FACILITY_MLSTR, 1003)
#define MLSTR_E_STRBUFNOTAVAILABLE MAKE_HRESULT(1, FACILITY_MLSTR, 1004)
/////////////////////////////////////////////////////////////////////////////
// CMLStr
class ATL_NO_VTABLE CMLStr :
public CComObjectRoot,
public CComCoClass<CMLStr, &CLSID_CMLangString>,
#ifdef ASTRIMPL
public IMLangString
#else
public IMLangStringWStr
#endif
{
typedef HRESULT (CMLStr::*PFNUNLOCKPROC)(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen);
public:
CMLStr(void);
DECLARE_NO_REGISTRY()
BEGIN_COM_MAP(CMLStr)
COM_INTERFACE_ENTRY(IMLangString)
#ifdef ASTRIMPL
COM_INTERFACE_ENTRY_TEAR_OFF(IID_IMLangStringWStr, CMLStrW)
#else
COM_INTERFACE_ENTRY(IMLangStringWStr)
#endif
COM_INTERFACE_ENTRY_TEAR_OFF(IID_IMLangStringAStr, CMLStrA)
END_COM_MAP()
public:
// IMLangString
STDMETHOD(Sync)(/*[in]*/ BOOL fNoAccess);
STDMETHOD(GetLength)(/*[out, retval]*/ long* plLen);
STDMETHOD(SetMLStr)(/*[in]*/ long lDestPos, /*[in]*/ long lDestLen, /*[in]*/ IUnknown* pSrcMLStr, /*[in]*/ long lSrcPos, /*[in]*/ long lSrcLen);
STDMETHOD(GetMLStr)(/*[in]*/ long lSrcPos, /*[in]*/ long lSrcLen, /*[in]*/ IUnknown* pUnkOuter, /*[in]*/ DWORD dwClsContext, /*[in]*/ const IID* piid, /*[out]*/ IUnknown** ppDestMLStr, /*[out]*/ long* plDestPos, /*[out]*/ long* plDestLen);
#ifndef ASTRIMPL
// IMLangStringWStr
STDMETHOD(SetWStr)(/*[in]*/ long lDestPos, /*[in]*/ long lDestLen, /*[in, size_is(cchSrc)]*/ const WCHAR* pszSrc, /*[in]*/ long cchSrc, /*[out]*/ long* pcchActual, /*[out]*/ long* plActualLen);
STDMETHOD(SetStrBufW)(/*[in]*/ long lDestPos, /*[in]*/ long lDestLen, /*[in]*/ IMLangStringBufW* pSrcBuf, /*[out]*/ long* pcchActual, /*[out]*/ long* plActualLen);
STDMETHOD(GetWStr)(/*[in]*/ long lSrcPos, /*[in]*/ long lSrcLen, /*[out, size_is(cchDest)]*/ WCHAR* pszDest, /*[in]*/ long cchDest, /*[out]*/ long* pcchActual, /*[out]*/ long* plActualLen);
STDMETHOD(GetStrBufW)(/*[in]*/ long lSrcPos, /*[in]*/ long lSrcMaxLen, /*[out]*/ IMLangStringBufW** ppDestBuf, /*[out]*/ long* plDestLen);
STDMETHOD(LockWStr)(/*[in]*/ long lSrcPos, /*[in]*/ long lSrcLen, /*[in]*/ long lFlags, /*[in]*/ long cchRequest, /*[out, size_is(,*pcchDest)]*/ WCHAR** ppszDest, /*[out]*/ long* pcchDest, /*[out]*/ long* plDestLen);
STDMETHOD(UnlockWStr)(/*[in, size_is(cchSrc)]*/ const WCHAR* pszSrc, /*[in]*/ long cchSrc, /*[out]*/ long* pcchActual, /*[out]*/ long* plActualLen);
#endif
STDMETHOD(SetLocale)(/*[in]*/ long lDestPos, /*[in]*/ long lDestLen, /*[in]*/ LCID locale);
STDMETHOD(GetLocale)(/*[in]*/ long lSrcPos, /*[in]*/ long lSrcMaxLen, /*[out]*/ LCID* plocale, /*[out]*/ long* plLocalePos, /*[out]*/ long* plLocaleLen);
#ifdef ASTRIMPL
protected:
class CLockInfo
{
protected:
class CLockInfoEntry
{
public:
void* m_psz;
PFNUNLOCKPROC m_pfnUnlockProc;
long m_lFlags;
UINT m_uCodePage;
long m_lPos;
long m_lLen;
long m_cchPos;
long m_cchLen;
};
public:
CLockInfo(CMLStr* pMLStr) : m_pMLStr(pMLStr)
{
m_nLockCount = 0;
m_pLockArray = NULL;
}
~CLockInfo(void)
{
UnlockAll();
}
HRESULT UnlockAll(void);
HRESULT StartLock(BOOL fWrite)
{
if (fWrite && !m_nLockCount)
m_nLockCount = -1; // Negative means write lock
else if (!fWrite && m_nLockCount >= 0)
m_nLockCount++;
else
return MLSTR_E_ACCESSDENIED;
return S_OK;
}
HRESULT EndLock(BOOL fWrite)
{
ASSERT(m_nLockCount);
if (fWrite)
m_nLockCount = 0;
else
m_nLockCount--;
return S_OK;
}
HRESULT Lock(PFNUNLOCKPROC pfnUnlockProc, long lFlags, UINT uCodePage, void* psz, long lPos, long lLen, long cchPos, long cchLen);
HRESULT Find(const void* psz, long cch, void** ppKey);
HRESULT Unlock(void* pKey, const void* psz, long cch, long* pcchActual, long* plActualLen);
long GetFlags(void* pKey) {return ((CLockInfoEntry*)pKey)->m_lFlags;}
UINT GetCodePage(void* pKey) {return ((CLockInfoEntry*)pKey)->m_uCodePage;}
long GetPos(void* pKey) {return ((CLockInfoEntry*)pKey)->m_lPos;}
long GetLen(void* pKey) {return ((CLockInfoEntry*)pKey)->m_lLen;}
long GetCChPos(void* pKey) {return ((CLockInfoEntry*)pKey)->m_cchPos;}
long GetCChLen(void* pKey) {return ((CLockInfoEntry*)pKey)->m_cchLen;}
protected:
CMLStr* const m_pMLStr;
int m_nLockCount;
CLockInfoEntry* m_pLockArray;
};
class CMLStrBufStandardW : public CMLStrBufW
{
protected:
LPVOID MemAlloc(ULONG cb) {return ::CoTaskMemAlloc(cb);}
LPVOID MemRealloc(LPVOID pv, ULONG cb) {return ::CoTaskMemRealloc(pv, cb);}
void MemFree(LPVOID pv) {::CoTaskMemFree(pv);}
long RoundBufSize(long cchStr);
};
#endif
public:
// Called from CMLStrW and CMLStrA
#ifdef ASTRIMPL
class CLock
{
public:
CLock(BOOL fWrite, CMLStr* pMLStr, HRESULT& hr) : m_fWrite(fWrite), m_pMLStr(pMLStr) {m_fLocked = (SUCCEEDED(hr) && SUCCEEDED(hr = m_pMLStr->GetLockInfo()->StartLock(m_fWrite)));}
~CLock(void) {if (m_fLocked) m_pMLStr->GetLockInfo()->EndLock(m_fWrite);}
HRESULT FallThrough(void) {m_fLocked = FALSE; return S_OK;} // Don't call EndLock in destructor
protected:
const BOOL m_fWrite;
CMLStr* const m_pMLStr;
BOOL m_fLocked;
};
#endif
HRESULT PrepareMLStrBuf(void);
HRESULT SetStrBufCommon(void* pMLStrX, long lDestPos, long lDestLen, UINT uCodePage, IMLangStringBufW* pSrcBufW, IMLangStringBufA* pSrcBufA, long* pcchActual, long* plActualLen);
#ifdef ASTRIMPL
HRESULT UnlockStrCommon(const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen);
#endif
HRESULT CheckThread(void) {return (m_dwThreadID == ::GetCurrentThreadId()) ? S_OK : E_FAIL;}
HRESULT RegularizePosLen(long* plPos, long* plLen);
HRESULT GetLen(long cchOffset, long cchLen, long* plLen);
HRESULT GetCCh(long cchOffset, long lLen, long* pcchLen);
static HRESULT CalcLenW(const WCHAR*, long cchLen, long* plLen) {if (plLen) *plLen = cchLen; return S_OK;}
static HRESULT CalcLenA(UINT uCodePage, const CHAR*, long cchLen, long* plLen);
static HRESULT CalcCChW(const WCHAR*, long lLen, long* pcchLen) {if (pcchLen) *pcchLen = lLen; return S_OK;}
static HRESULT CalcCChA(UINT uCodePage, const CHAR*, long lLen, long* pcchLen);
static HRESULT CalcBufSizeW(long lLen, long* pcchSize) {if (pcchSize) *pcchSize = lLen; return S_OK;}
static HRESULT CalcBufSizeA(long lLen, long* pcchSize) {if (pcchSize) *pcchSize = lLen * 2; return S_OK;}
static HRESULT ConvAStrToWStr(UINT uCodePage, const CHAR* pszSrc, long cchSrc, WCHAR* pszDest, long cchDest, long* pcchActualA, long* pcchActualW, long* plActualLen);
static HRESULT ConvWStrToAStr(BOOL fCanStopAtMiddle, UINT uCodePage, const WCHAR* pszSrc, long cchSrc, CHAR* pszDest, long cchDest, long* pcchActualA, long* pcchActualW, long* plActualLen);
IMLangStringBufW* GetMLStrBufW(void) const {return m_pMLStrBufW;}
void SetMLStrBufW(IMLangStringBufW* pBuf) {m_pMLStrBufW = pBuf;}
IMLangStringBufA* GetMLStrBufA(void) const {return m_pMLStrBufA;}
void SetMLStrBufA(IMLangStringBufA* pBuf) {m_pMLStrBufA = pBuf;}
UINT GetCodePage(void) const {return m_uCodePage;}
void SetCodePage(UINT uCodePage) {m_uCodePage = uCodePage;}
long GetBufFlags(void) const {return m_lBufFlags;}
void SetBufFlags(long lBufFlags) {m_lBufFlags = lBufFlags;}
long GetBufCCh(void) const {return m_cchBuf;}
void SetBufCCh(long cchBuf) {m_cchBuf = cchBuf;}
LCID GetLocale(void) const {return m_locale;}
void SetLocale(LCID locale) {m_locale = locale;}
#ifdef ASTRIMPL
CLockInfo* GetLockInfo(void) {return &m_LockInfo;}
#else
BOOL IsLocked(void) const {return (m_lLockFlags != 0);}
BOOL IsDirectLock(void) const {return m_fDirectLock;}
void SetDirectLockFlag(BOOL fDirectLock) {m_fDirectLock = fDirectLock;}
long GetLockFlags(void) const {return m_lLockFlags;}
void SetLockFlags(long lFlags) {m_lLockFlags = lFlags;}
#endif
HRESULT MemAlloc(ULONG cb, void** ppv) {void* pv = ::CoTaskMemAlloc(cb); if (ppv) *ppv = pv; return (pv) ? S_OK : E_OUTOFMEMORY;}
HRESULT MemFree(void* pv) {::CoTaskMemFree(pv); return S_OK;}
#ifdef ASTRIMPL
HRESULT UnlockWStrDirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen);
HRESULT UnlockWStrIndirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen);
HRESULT UnlockAStrDirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen);
HRESULT UnlockAStrIndirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen);
#endif
protected:
~CMLStr(void);
#ifndef ASTRIMPL
static HRESULT ConvertMLStrBufAToWStr(UINT uCodePage, IMLangStringBufA* pMLStrBufA, long cchSrcPos, long cchSrcLen, WCHAR* pszBuf, long cchBuf, long* pcchActual);
static HRESULT ConvertWStrToMLStrBufA(const WCHAR* pszSrc, long cchSrc, UINT uCodePage, IMLangStringBufA* pMLStrBufA, long cchDestPos, long cchDestLen);
#endif
DWORD m_dwThreadID;
IMLangStringBufW* m_pMLStrBufW;
IMLangStringBufA* m_pMLStrBufA;
UINT m_uCodePage;
long m_lBufFlags;
long m_cchBuf;
LCID m_locale;
#ifdef ASTRIMPL
CLockInfo m_LockInfo;
#else
BOOL m_fDirectLock;
long m_lLockFlags;
WCHAR* m_pszLockBuf;
long m_cchLockPos;
long m_cchLockLen;
long m_lLockPos;
long m_lLockLen;
#endif
};
#endif //__MLSTR_H_
#else // NEWMLSTR
// MLStr.h : Declaration of the CMLStr
#ifndef __MLSTR_H_
#define __MLSTR_H_
#include "mlstrw.h" // IMLangStringWStrImpl
#include "mlstra.h" // IMLangStringAStrImpl
#include "util.h"
/////////////////////////////////////////////////////////////////////////////
// CMLStr
class ATL_NO_VTABLE CMLStr :
public CComObjectRoot,
public CComCoClass<CMLStr, &CLSID_CMLangString>,
public IMLangString,
public IMLStrAttrNotifySink,
public IConnectionPointContainerImpl<CMLStr>,
public IConnectionPointImpl<CMLStr, &IID_IMLangStringNotifySink>
{
public:
CMLStr();
DECLARE_NO_REGISTRY()
BEGIN_COM_MAP(CMLStr)
COM_INTERFACE_ENTRY(IMLangString)
COM_INTERFACE_ENTRY_TEAR_OFF(IID_IMLangStringWStr, CMLStrW)
COM_INTERFACE_ENTRY_TEAR_OFF(IID_IMLangStringAStr, CMLStrA)
COM_INTERFACE_ENTRY(IMLStrAttrNotifySink)
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CMLStr)
CONNECTION_POINT_ENTRY(IID_IMLangStringNotifySink)
END_CONNECTION_POINT_MAP()
public:
// IMLangString
STDMETHOD(LockMLStr)(/*[in]*/ long lPos, /*[in]*/ long lLen, /*[in]*/ DWORD dwFlags, /*[out]*/ DWORD* pdwCookie, /*[out]*/ long* plActualPos, /*[out]*/ long* plActualLen);
STDMETHOD(UnlockMLStr)(/*[in]*/ DWORD dwCookie);
STDMETHOD(GetLength)(/*[out, retval]*/ long* plLen);
STDMETHOD(SetMLStr)(/*[in]*/ long lDestPos, /*[in]*/ long lDestLen, /*[in]*/ IUnknown* pSrcMLStr, /*[in]*/ long lSrcPos, /*[in]*/ long lSrcLen);
STDMETHOD(RegisterAttr)(/*[in]*/ IUnknown* pUnk, /*[out]*/ DWORD* pdwCookie);
STDMETHOD(UnregisterAttr)(/*[in]*/ DWORD dwCookie);
STDMETHOD(EnumAttr)(/*[out]*/ IEnumUnknown** ppEnumUnk);
STDMETHOD(FindAttr)(/*[in]*/ REFIID riid, /*[in]*/ LPARAM lParam, /*[out]*/ IUnknown** ppUnk);
// IMLStrAttrNotifySink
STDMETHOD(OnRequestEdit)(/*[in]*/ long lDestPos, /*[in]*/ long lDestLen, /*[in]*/ long lNewLen, /*[in]*/ REFIID riid, /*[in]*/ LPARAM lParam, /*[in]*/ IUnknown* pUnk);
STDMETHOD(OnCanceledEdit)(/*[in]*/ long lDestPos, /*[in]*/ long lDestLen, /*[in]*/ long lNewLen, /*[in]*/ REFIID riid, /*[in]*/ LPARAM lParam, /*[in]*/ IUnknown* pUnk);
STDMETHOD(OnChanged)(/*[in]*/ long lDestPos, /*[in]*/ long lDestLen, /*[in]*/ long lNewLen, /*[in]*/ REFIID riid, /*[in]*/ LPARAM lParam, /*[in]*/ IUnknown* pUnk);
//---------------------------------------------------------------------------
protected:
struct LOCKINFO
{
long lPos;
long lLen;
DWORD dwFlags;
DWORD dwThrd;
};
//---------------------------------------------------------------------------
protected:
class CLockList : public CMLListFast
{
protected:
struct CCell : public CMLListFast::CCell
{
LOCKINFO m_linfo;
};
public:
inline CLockList(void) : CMLListFast(sizeof(CCell), sizeof(CCell) * 8) {}
inline HRESULT SetLock(void* pv, long lPos, long lLen, DWORD dwFlags, DWORD dwThrd)
{
((CCell*)pv)->m_linfo.lPos = lPos;
((CCell*)pv)->m_linfo.lLen = lLen;
((CCell*)pv)->m_linfo.dwFlags = dwFlags;
((CCell*)pv)->m_linfo.dwThrd = dwThrd;
return S_OK;
}
inline HRESULT GetLockInfo(void* pv, LOCKINFO** pplinfo)
{
*pplinfo = &((CCell*)pv)->m_linfo;
return S_OK;
}
};
//---------------------------------------------------------------------------
protected:
class CAttrList : public CMLListLru
{
protected:
struct CCell : public CMLListLru::CCell
{
IMLStrAttr* m_pAttr;
DWORD m_dwCookie;
};
public:
inline CAttrList(void) : CMLListLru(sizeof(CCell), sizeof(CCell) * 8) {}
inline IMLStrAttr* GetAttr(void* pv) {return ((CCell*)pv)->m_pAttr;}
inline void SetAttr(void* pv, IMLStrAttr* pAttr) {((CCell*)pv)->m_pAttr = pAttr;}
inline DWORD GetCookie(void* pv) const {return ((CCell*)pv)->m_dwCookie;}
inline void SetCookie(void* pv, DWORD dwCookie) {((CCell*)pv)->m_dwCookie = dwCookie;}
};
//---------------------------------------------------------------------------
// IEnumUnknown object for IMLangString::EnumAttr()
protected:
class ATL_NO_VTABLE CEnumAttr :
public CComObjectRoot,
public IEnumUnknown
{
public:
CEnumAttr(void);
~CEnumAttr(void);
void Init(CMLStr* pMLStr);
BEGIN_COM_MAP(CEnumAttr)
COM_INTERFACE_ENTRY(IEnumUnknown)
END_COM_MAP()
STDMETHOD(Next)(ULONG celt, IUnknown** rgelt, ULONG* pceltFetched);
STDMETHOD(Skip)(ULONG celt);
STDMETHOD(Reset)(void);
STDMETHOD(Clone)(IEnumUnknown** ppEnum);
protected:
CMLStr* m_pMLStr;
void* m_pv;
};
friend class CEnumAttr;
//---------------------------------------------------------------------------
// Fire notification to all of IMLangStringNotifySink advised.
protected:
class CFire : public CFireConnection<IMLangStringNotifySink, &IID_IMLangStringNotifySink>
{
public:
inline CFire(HRESULT& rhr, CMLStr* const pMLStr) :
CFireConnection<IMLangStringNotifySink, &IID_IMLangStringNotifySink>(rhr)
{
if (SUCCEEDED(*m_phr) &&
FAILED(*m_phr = pMLStr->EnumConnections(&m_pEnumConn)))
{
m_pEnumConn = NULL;
}
}
};
//---------------------------------------------------------------------------
protected:
~CMLStr(void);
HRESULT CheckAccessValidation(long lPos, long lLen, DWORD dwFlags, DWORD dwThrd, long* plActualPos, long* plActualLen);
inline HRESULT StartEndConnectionAttr(IUnknown* const pUnk, DWORD* const pdwCookie, DWORD dwCookie)
{
return ::StartEndConnection(pUnk, &IID_IMLStrAttrNotifySink, (IMLStrAttrNotifySink*)this, pdwCookie, dwCookie);
}
protected:
long m_lLen;
CLockList m_lock;
CAttrList m_attr;
HANDLE m_hUnlockEvent;
int m_cWaitUnlock;
HANDLE m_hZeroEvent;
};
#endif //__MLSTR_H_
#endif // NEWMLSTR