411 lines
16 KiB
C++
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
|