mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
4.6 KiB
256 lines
4.6 KiB
#ifndef _MISCHLPR_H_
|
|
#define _MISCHLPR_H_
|
|
|
|
#include <objbase.h>
|
|
|
|
#include "dbg.h"
|
|
#include "tfids.h"
|
|
|
|
#define UNREF_PARAM(a)
|
|
#define IID_PPV_ARG(IType, ppType) IID_##IType, reinterpret_cast<void**>(static_cast<IType**>(ppType))
|
|
|
|
class CRefCounted
|
|
{
|
|
#ifdef DEBUG
|
|
private:
|
|
void _TraceHelper(LPCTSTR pszOper, ULONG cRef, LPCTSTR pszObjName,
|
|
LPCSTR pszFile, const int iLine)
|
|
{
|
|
LPTSTR pszFinal;
|
|
WCHAR szwBuf[MAX_PATH + 12];
|
|
CHAR szBuf[MAX_PATH + 12];
|
|
int c = lstrlenA(pszFile);
|
|
LPCSTR pszFileName;
|
|
|
|
while (c && ('\\' != *(pszFile + c)))
|
|
{
|
|
--c;
|
|
}
|
|
|
|
pszFileName = pszFile + c + 1;
|
|
|
|
wsprintfA(szBuf, "<%s, %d>", pszFileName, iLine);
|
|
|
|
#ifdef UNICODE
|
|
pszFinal = szwBuf;
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, szBuf, lstrlenA(szBuf) + 1, szwBuf,
|
|
sizeof(szwBuf) / sizeof(WCHAR));
|
|
#else
|
|
pszFinal = szBuf;
|
|
#endif
|
|
|
|
if (pszObjName)
|
|
{
|
|
TRACE(TF_RCADDREF | TF_NOFILEANDLINE, TEXT("%s {%s} %s: %d"),
|
|
pszFinal, pszObjName, pszOper, cRef);
|
|
}
|
|
else
|
|
{
|
|
TRACE(TF_NOFILEANDLINE | TF_RCADDREF, TEXT("%s %s: %d"), pszFinal,
|
|
pszOper, cRef);
|
|
}
|
|
|
|
}
|
|
|
|
protected:
|
|
void _RCCreate(LPCSTR pszFile, const int iLine)
|
|
{
|
|
_TraceHelper(TEXT(" Create"), 1, _pszRCAddRefName, pszFile, iLine);
|
|
}
|
|
|
|
LPTSTR _pszRCAddRefName;
|
|
|
|
public:
|
|
ULONG _RCGetRefCount()
|
|
{
|
|
return _cRef;
|
|
}
|
|
|
|
virtual ULONG RCAddRef(LPCSTR pszFile, const int iLine)
|
|
{
|
|
ULONG cRef = ::InterlockedIncrement((LONG*)&_cRef);
|
|
|
|
_TraceHelper(TEXT(" AddRef"), cRef, _pszRCAddRefName, pszFile, iLine);
|
|
|
|
return cRef;
|
|
}
|
|
|
|
virtual ULONG RCRelease(LPCSTR pszFile, const int iLine)
|
|
{
|
|
ULONG cRef = ::InterlockedDecrement((LONG*)&_cRef);
|
|
|
|
_TraceHelper(TEXT("Release"), cRef, _pszRCAddRefName, pszFile, iLine);
|
|
|
|
if (!cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return cRef;
|
|
}
|
|
|
|
#define RCAddRef() RCAddRef(__FILE__, __LINE__)
|
|
#define RCRelease() RCRelease(__FILE__, __LINE__)
|
|
|
|
#else
|
|
public:
|
|
ULONG RCAddRef() { return ::InterlockedIncrement((LONG*)&_cRef); }
|
|
ULONG RCRelease()
|
|
{
|
|
ULONG cRef = ::InterlockedDecrement((LONG*)&_cRef);
|
|
|
|
if (!cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return cRef;
|
|
}
|
|
#endif
|
|
|
|
CRefCounted() : _cRef(1)
|
|
#ifdef DEBUG
|
|
, _pszRCAddRefName(NULL)
|
|
#endif
|
|
{}
|
|
virtual ~CRefCounted() {}
|
|
|
|
private:
|
|
ULONG _cRef;
|
|
};
|
|
|
|
class CRefCountedCritSect : public CRefCounted, public CRITICAL_SECTION
|
|
{};
|
|
|
|
class CCriticalSection : CRITICAL_SECTION
|
|
{
|
|
public:
|
|
void Init()
|
|
{
|
|
InitializeCriticalSection(this);
|
|
_fInited = TRUE;
|
|
|
|
#ifdef DEBUG
|
|
_iLevel = 0;
|
|
#endif
|
|
}
|
|
void Enter()
|
|
{
|
|
ASSERT(_fInited);
|
|
EnterCriticalSection(this);
|
|
#ifdef DEBUG
|
|
++_iLevel;
|
|
#endif
|
|
}
|
|
void Leave()
|
|
{
|
|
ASSERT(_fInited);
|
|
#ifdef DEBUG
|
|
--_iLevel;
|
|
#endif
|
|
LeaveCriticalSection(this);
|
|
}
|
|
|
|
void Delete()
|
|
{
|
|
if (_fInited)
|
|
{
|
|
_fInited = FALSE;
|
|
DeleteCriticalSection(this);
|
|
}
|
|
}
|
|
|
|
BOOL IsInitialized()
|
|
{
|
|
return _fInited;
|
|
}
|
|
|
|
BOOL _fInited;
|
|
#ifdef DEBUG
|
|
BOOL IsInside()
|
|
{
|
|
ASSERT(_fInited);
|
|
|
|
return _iLevel;
|
|
}
|
|
|
|
DWORD _iLevel;
|
|
#endif
|
|
};
|
|
|
|
class CThreadTask
|
|
{
|
|
public:
|
|
virtual ~CThreadTask() {}
|
|
|
|
public:
|
|
// Uses CreateThread, delete 'this' at the end
|
|
HRESULT RunWithTimeout(DWORD dwTimeout);
|
|
|
|
// Uses Thread Pool, delete 'this' at the end
|
|
HRESULT Run();
|
|
|
|
// Run on 'this' thread, does NOT delete 'this' at the end
|
|
HRESULT RunSynchronously();
|
|
|
|
protected:
|
|
virtual HRESULT _DoStuff() = 0;
|
|
|
|
private:
|
|
static DWORD WINAPI _ThreadProc(void* pv);
|
|
};
|
|
|
|
template<typename TDataPtr>
|
|
HRESULT _AllocMemoryChunk(DWORD cbSize, TDataPtr* pdataOut)
|
|
{
|
|
HRESULT hr;
|
|
|
|
*pdataOut = (TDataPtr)LocalAlloc(LPTR, cbSize);
|
|
|
|
if (*pdataOut)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
template<typename TDataPtr>
|
|
HRESULT _DupMemoryChunk(TDataPtr pdata, DWORD cbSize, TDataPtr* pdataOut)
|
|
{
|
|
HRESULT hr;
|
|
*pdataOut = (TDataPtr)LocalAlloc(LPTR, cbSize);
|
|
|
|
if (*pdataOut)
|
|
{
|
|
CopyMemory((void*)*pdataOut, pdata, cbSize);
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
template<typename TDataPtr>
|
|
HRESULT _FreeMemoryChunk(TDataPtr pdata)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (LocalFree((HLOCAL)pdata))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
#endif //_MISCHLPR_H_
|