#pragma comment(lib, "USER32" )
#include <crtdbg.h>
#include <tchar.h>
#pragma comment(lib, "version.lib")
#define MTVERIFY(a) (a)
#if 0
#define SHOWERROR(a) PrintError(a,__FILE__,__LINE__,GetLastError())

#ifdef DEBUG
#define MTASSERT(a) _ASSERTE(a)
#define MTVERIFY(a) if (!(a)) PrintError(#a,__FILE__,__LINE__,GetLastError())
#else /*DEBUG*/
#define MTASSERT(a)
#define MTVERIFY(a) (a)
#endif /*DEBUG*/

__inline void PrintError(LPCTSTR linedesc, LPCTSTR filename, int lineno, DWORD errnum)
{
	LPTSTR lpBuffer;
	TCHAR errbuf[256];

#ifdef _WINDOWS_
	TCHAR modulename[MAX_PATH];
#else //_WINDOWS_
	DWORD numread;
#endif //_WINDOWS_

	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL,
		errnum,
		LANG_NEUTRAL,
		(LPTSTR)&lpBuffer,
		0,
		NULL
		);
	_stprintf(errbuf, _T("\nThe following call failed at line %d in %s:\n\n %s\n\nReason: %s\n"), 
		lineno, filename, linedesc, lpBuffer);

#ifndef _WINDOWS_
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), errbuf, lstrlen(errbuf), &numread, FALSE );
	Sleep(3000);
#else //_WINDOWS_
	GetModuleFileName(NULL, modulename, MAX_PATH);
	MessageBox(NULL, errbuf, modulename, MB_ICONWARNING|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
	OutputDebugString(errbuf);
#endif //_WINDOWS_

	LocalFree(lpBuffer);
	//exit(EXIT_FAILURE);
}
#endif



__inline void WaitTillThreadActive(HANDLE &handle)
{
	if(handle != INVALID_HANDLE_VALUE)
	{
		BOOL rc = FALSE;
		DWORD ec = 0;
		for(;;)
		{
			rc = GetExitCodeThread(handle, &ec);
			if(rc && (ec == STILL_ACTIVE))
				break;
			Sleep(500);
		}
	}
}
// obsolete
/*
__inline void WaitTillThreadExited(HANDLE &handle, DWORD dwMilliseconds = 3000)
{
	if(handle != INVALID_HANDLE_VALUE)
	{
		BOOL rc = FALSE;
		DWORD ec = 0;
		DWORD dwStart = GetTickCount();
		for(;;)
		{
			if(GetTickCount() - dwStart >= dwMilliseconds)
			{
				::TerminateThread(handle, 0xffffffff);
				CloseHandle(handle);
				handle = INVALID_HANDLE_VALUE;
				break;
			}
			if(handle == INVALID_HANDLE_VALUE)
				break;
			rc = GetExitCodeThread(handle, &ec);
			if(rc && (ec != STILL_ACTIVE))
			{
				CloseHandle(handle);
				handle = INVALID_HANDLE_VALUE;
				break;
			}
			Sleep(500);
		}
	}
}
*/

__forceinline void WaitTillThreadExited(HANDLE &handle, DWORD dwMilliseconds = 5000)
{
	if(handle == INVALID_HANDLE_VALUE)
		return;
	DWORD ret = ::WaitForSingleObject(handle, dwMilliseconds);
	if(ret != WAIT_OBJECT_0)
	{	//::TerminateThread(handle, 0xffffffff);
	}
	CloseHandle(handle);
	handle = INVALID_HANDLE_VALUE;
}

__inline LPTSTR GetModuleFilePath()
{
	static TCHAR szPath[MAX_PATH] = {'\0'};
	if(lstrlen(szPath) != 0)
		return szPath;
	
	TCHAR szExe[MAX_PATH];
	GetModuleFileName(GetModuleHandle(NULL), szExe, MAX_PATH);
	int len = lstrlen(szExe);
	for(int i = len; i > 0; i--)
	{
		if(szExe[i] == '\\')
		{
			szExe[i] = '\0';
			lstrcpy(szPath, szExe);
			break;
		}
	}
	return szPath;
}

/////////*********************�Զ����********************////////////////////////
//��ȫɾ����ͨ���ڴ�
#define SAFEDELETEP(p) {if(p){delete (p); (p)=NULL;}}

#define SAFEDELETEARR(pArr) {if((pArr)){delete[] (pArr); (pArr)=NULL;}}

//��ȫɾ���Ի�������ڴ�
#define SAFEDELETEDLG(pDlg) {\
	if ((pDlg)) {\
		if (::IsWindow(pDlg->m_hWnd)) {\
			(pDlg)->DestroyWindow();\
		}\
		delete (pDlg);\
		(pDlg)=NULL;\
	}\
}

//�رպ��Ķ�����
#define CLOSEHANDLE(h){\
	if (h != INVALID_HANDLE_VALUE && h != NULL) {\
		::CloseHandle(h);\
		h = INVALID_HANDLE_VALUE;\
	}\
}

#define CLOSESOCKET(s){\
	if(s != INVALID_SOCKET){\
		::closesocket(s); \
		s = INVALID_SOCKET;\
	}\
}

#ifdef _DEBUG
#define VERIFYPTR(p, cb) {MTVERIFY(!IsBadWritePtr(p, cb));}
#else
#define VERIFYPTR(p, cb)
#endif


/**************UNICODE-ANSI mutually transform**************************/
// need be manuly delete
__forceinline LPSTR Utf16ToAnsi(const wchar_t * const wSrc)
{
	char* pElementText;
	int iTextLen;
	iTextLen = WideCharToMultiByte( CP_ACP,	0, wSrc, -1, NULL,0, NULL, NULL );
	pElementText = new char[iTextLen + 1];
	memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
	::WideCharToMultiByte( CP_ACP,0,wSrc,-1,pElementText,iTextLen,NULL,NULL);

	return pElementText;
}

__forceinline BOOL Utf16ToAnsiUseCharArray(const wchar_t * const wSrc, 
										   char *ansiArr, WORD ansiArrLen)
{
	int iTextLen = WideCharToMultiByte( CP_ACP,	0, wSrc, -1, NULL,0, NULL, NULL );
	if(iTextLen < ansiArrLen){
		memset( ( void* )ansiArr, 0, sizeof( char ) * ( iTextLen + 1 ) );
		::WideCharToMultiByte(CP_ACP,0,wSrc,-1,ansiArr,iTextLen,NULL,NULL);
		return TRUE;
	}
	return FALSE;
}

__forceinline wchar_t* AnsiToUtf16(PCSTR ansiSrc)
{
	wchar_t *pWide;
	int  iUnicodeLen = ::MultiByteToWideChar( CP_ACP,
        0, ansiSrc, -1, NULL, 0);
	pWide = new  wchar_t[iUnicodeLen + 1]; 
	memset(pWide, 0, (iUnicodeLen+1) * sizeof(wchar_t) );
	::MultiByteToWideChar( CP_ACP, 0, ansiSrc, -1, (LPWSTR)pWide, iUnicodeLen );  
	return pWide;
}

__forceinline BOOL AnsiToUtf16Array(PCSTR ansiSrc, wchar_t* warr, int warr_len)
{
	int  iUnicodeLen = ::MultiByteToWideChar( CP_ACP,
        0, ansiSrc, -1, NULL, 0);
	if(warr_len >= iUnicodeLen){
		memset(warr, 0, (iUnicodeLen+1) * sizeof(wchar_t) );
		::MultiByteToWideChar( CP_ACP, 0, ansiSrc, -1, (LPWSTR)warr, iUnicodeLen );
		return TRUE;
	}
	return FALSE;
}

__forceinline wchar_t* Utf8ToUtf16(PCSTR ansiSrc)
{
	wchar_t *pWide;
	int  iUnicodeLen = ::MultiByteToWideChar( CP_UTF8,
		0, ansiSrc, -1, NULL, 0);
	pWide = new  wchar_t[iUnicodeLen + 1]; 
	memset(pWide, 0, (iUnicodeLen+1) * sizeof(wchar_t) );
	::MultiByteToWideChar( CP_UTF8, 0, ansiSrc, -1, (LPWSTR)pWide, iUnicodeLen );  
	return pWide;
}

__inline const char* Utf16ToUtf8(const wchar_t* utf16, int& out_len)
{
	out_len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, 0, 0);
	char *p8 = new  char[out_len + 1];
	memset(p8, 0, (out_len + 1) * sizeof(wchar_t));
	::WideCharToMultiByte(CP_UTF8, 0, utf16, -1, p8, out_len, 0, 0);
	return p8;
}


__inline const char* Utf16ToGbk(const wchar_t* utf16)
{
	//WideCharToMultiByte(CP_GBK)
}


/*
__forceinline CString GetFileVersion()
{   
	int iVerInfoSize;
	char *pBuf;
	CString asVer= _T("");
	VS_FIXEDFILEINFO *pVsInfo;
	unsigned int iFileInfoSize = sizeof(VS_FIXEDFILEINFO);
	TCHAR fileName[MAX_PATH];
	GetModuleFileName(NULL, fileName, MAX_PATH);
	iVerInfoSize = GetFileVersionInfoSize(fileName, NULL); 
    
	if(iVerInfoSize != 0){   
		pBuf = new char[iVerInfoSize];
		if(GetFileVersionInfo(fileName, 0, iVerInfoSize, pBuf)){   
			if(VerQueryValue(pBuf, _T("//"), (void**)&pVsInfo, &iFileInfoSize)){   
				asVer.Format(_T("%d.%d.%d.%d"),
					HIWORD(pVsInfo->dwFileVersionMS),
					LOWORD(pVsInfo->dwFileVersionMS),
					HIWORD(pVsInfo->dwFileVersionLS),
					LOWORD(pVsInfo->dwFileVersionLS));
			}   
		}   
		delete pBuf;   
	}   
	return asVer;   
}  
*/