Эх сурвалжийг харах

通信库完成添加(使用静态库需要添加HPSOCKET_STATIC_LIB宏)

Jeff 6 жил өмнө
parent
commit
2aba9eb438

+ 986 - 0
source/hook/hp-src/FuncHelper.cpp

@@ -0,0 +1,986 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "stdafx.h"
+#include "FuncHelper.h"
+#include "WaitFor.h"
+
+#ifndef _WIN32_WCE
+	#define CloseToolhelp32Snapshot(h)	CloseHandle(h)
+
+	#include <psapi.h>
+	#include <Shellapi.h>
+
+	#pragma comment(lib, "Psapi")
+#else
+	#pragma comment(lib, "Toolhelp")
+#endif
+
+BYTE DoubleCharToByte(LPCTSTR psValue)
+{ 
+	return (BYTE)DOUBLECHARTOVALUE(psValue);
+}
+
+LPTSTR ByteToDoubleChar(BYTE b, LPTSTR des)
+{
+	VALUETODOUBLECHAR(des, b);
+	return des;
+}
+
+UINT HexStrToInt(LPCTSTR pHexText, int len)
+{
+	LPTSTR pTemp	= (LPTSTR)pHexText;
+	int Val			= 0;
+	int iLen		= lstrlen(pHexText);
+	if(len > 0 && len < iLen)
+		iLen = len;
+	if(iLen % 2)
+	{
+		pTemp = (TCHAR*)_alloca(sizeof(TCHAR) * ((++iLen) + 1));
+		lstrcpyn(pTemp+1, pHexText, iLen);
+		pTemp[0] = '0';
+	}
+
+	for(int i = 0; i < iLen; i+=2)
+		Val += (DOUBLECHARTOVALUE(&pTemp[i]) << ((iLen - i)/2 - 1) * 8);
+
+	return Val;
+}
+
+UINT DecStrToInt(LPCTSTR pDecText, int len)
+{
+	int Val = 0;
+	int iLen = lstrlen(pDecText);
+	if(len > 0 && len < iLen)
+	{
+		++len;
+		CString text;
+		LPTSTR ptext = text.GetBuffer(len);
+		lstrcpyn(ptext, pDecText, len);
+		Val = _ttol(ptext);
+		text.ReleaseBuffer();
+	}
+	else
+		Val = _ttol(pDecText);
+	return Val;
+}
+
+CString& IntToHexStr(CString& dest, UINT v, int len)
+{
+	if(len > 0)
+	{
+		CString format;
+		format.Format(_T("%%0%uX"), len);
+		dest.Format(format, v);
+		if(dest.GetLength() > len)
+			dest = dest.Right(len);
+	}
+	else
+		dest.Format(_T("%X"), v);
+	return dest;
+}
+
+CString& IntToDecStr(CString& dest, UINT v, int len)
+{
+	if(len > 0)
+	{
+		CString format;
+		format.Format(_T("%%0%uu"), len);
+		dest.Format(format, v);
+		if(dest.GetLength() > len)
+			dest = dest.Right(len);
+	}
+	else
+		dest.Format(_T("%u"), v);
+	return dest;
+}
+
+CString& HexAddrToDecAddr(CString& dest, LPCTSTR src, int destlen, int srclen)
+{
+	return IntToDecStr(dest, HexStrToInt(src, srclen), destlen);
+}
+CString& DecAddrToHexAddr(CString& dest, LPCTSTR src, int destlen, int srclen)
+{
+	return IntToHexStr(dest, DecStrToInt(src, srclen), destlen);
+}
+
+
+//-----------------------------MultiByte×Ö·ûºÍUnicode×Ö·ûÖ®¼äµÄת»»-----------------------------//
+
+EnCodePage GetCodePageByName(LPCTSTR lpszCodePageName)
+{
+	if(!lpszCodePageName || !*lpszCodePageName)
+		return XCP_ACP;
+	else if(_tcsicmp(lpszCodePageName, _T("GB2312")) == 0)
+		return XCP_GB2312;
+	else if(_tcsicmp(lpszCodePageName, _T("GBK")) == 0)
+		return XCP_GBK;
+	else if(_tcsicmp(lpszCodePageName, _T("UTF-8")) == 0)
+		return XCP_UTF8;
+	else if(_tcsicmp(lpszCodePageName, _T("UTF-7")) == 0)
+		return XCP_UTF7;
+	else if(_tcsicmp(lpszCodePageName, _T("BIG5")) == 0)
+		return XCP_BIG5;
+
+	return XCP_ACP;
+}
+
+BOOL MbcsToUnicode(const char* pszInString, WCHAR** ptrOutWStr, int& nSizeCount)
+{
+	return CPToUni(pszInString, ptrOutWStr, CP_ACP, nSizeCount);
+}
+
+BOOL UnicodeToMbcs(const WCHAR* pwzInString, char** ptrOutStr, int& nSizeCount)
+{
+	return UniToCP(pwzInString, ptrOutStr, CP_ACP, nSizeCount);
+}
+
+BOOL Utf8ToUnicode(const char* pszInString, WCHAR** ptrOutWStr, int& nSizeCount)
+{
+	return CPToUni(pszInString, ptrOutWStr, CP_UTF8, nSizeCount);
+}
+
+BOOL UnicodeToUtf8(const WCHAR* pwzInString, char** ptrOutStr, int& nSizeCount)
+{
+	return UniToCP(pwzInString, ptrOutStr, CP_UTF8, nSizeCount);
+}
+
+BOOL CPToUni(const char* pszInString, WCHAR** ptrOutWStr, unsigned int nCodePage, int& nSizeCount)
+{
+	nSizeCount = 0 ;
+	if( pszInString == nullptr || ptrOutWStr == nullptr )
+		return FALSE ;
+
+	nSizeCount = MultiByteToWideChar( nCodePage, 0, pszInString, -1, nullptr, 0 ) ;
+	if( 0 == nSizeCount )
+		return FALSE ;
+
+	(*ptrOutWStr) = new WCHAR[nSizeCount] ;
+	if( nullptr == (*ptrOutWStr) )
+		return FALSE ;
+
+	if( 0 == MultiByteToWideChar( nCodePage, 0, pszInString, -1, (*ptrOutWStr), nSizeCount ) )
+	{
+		delete[] (*ptrOutWStr);
+		return FALSE ;
+	}
+
+	return TRUE;
+}
+
+BOOL UniToCP(const WCHAR* pwzInString, char** ptrOutStr, unsigned int nCodePage, int& nSizeCount)
+{
+	nSizeCount = 0 ;
+	if( pwzInString == nullptr || ptrOutStr == nullptr )
+		return FALSE ;
+
+	nSizeCount = WideCharToMultiByte( nCodePage, 0, pwzInString, -1, nullptr, 0, nullptr, nullptr) ;
+	if( 0 == nSizeCount )
+		return FALSE ;
+
+	(*ptrOutStr) = new char[nSizeCount] ;
+	if( nullptr == (*ptrOutStr) )
+		return FALSE ;
+
+	if(0 == WideCharToMultiByte( nCodePage, 0, pwzInString, -1, (*ptrOutStr), nSizeCount, nullptr, nullptr))
+	{
+		delete[] (*ptrOutStr);
+		return FALSE ;
+	}
+
+	return TRUE;
+}
+
+int BytesToHex(const BYTE* pBytes, int nLength, LPTSTR* lpszDest)
+{
+	int des_length	= nLength * 2;
+
+	if(des_length > 0)
+	{
+		LPTSTR dest = new TCHAR[des_length + 1];
+		dest[des_length] = '\0';
+
+		TCHAR chs[3] = {0};
+		for(int i = 0; i < nLength; i++)
+		{
+			ByteToDoubleChar(pBytes[i], chs);
+			dest[2 * i] = chs[0];
+			dest[2 * i + 1] = chs[1];
+		}
+
+		*lpszDest = dest;
+	}
+	else
+		*lpszDest = nullptr;
+
+	return des_length;
+}
+
+int HexToBytes(LPCTSTR lpszHex, BYTE** ppBytes, int* pnLength)
+{
+	int src_length = lstrlen(lpszHex);
+	int des_length = src_length / 2;
+
+	*pnLength = des_length;
+
+	if(des_length > 0)
+	{
+		BYTE* pBytes = new BYTE[des_length];
+
+		for(int i = 0; i < des_length; i++)
+			pBytes[i] = DoubleCharToByte(&lpszHex[2 * i]);
+
+		*ppBytes = pBytes;
+	}
+	else
+		*ppBytes = nullptr;
+
+	return des_length;
+}
+
+CString& StrToHex(const TCHAR* src, CString& strDec)
+{
+	BYTE* t = (BYTE*)src;
+	int src_length = lstrlen(src) * sizeof(TCHAR);
+	strDec.Empty();
+
+#ifdef UNICODE
+	char* temp = nullptr;
+	UnicodeToMbcs(src, &temp, src_length);
+
+	src_length -= 1;
+	t = (BYTE*)temp;
+#else
+	t = (BYTE*)src;
+	src_length = lstrlen(src);
+#endif
+
+	for(int i = 0; i < src_length; ++i, ++t)
+	{
+		TCHAR tc[3] = {0, 0, 0};
+		VALUETODOUBLECHAR(tc, *t);
+		strDec += tc;
+	}
+
+#ifdef UNICODE
+	delete[] temp;
+#endif
+
+	return strDec;
+}
+
+CString& HexToStr(const TCHAR* src, CString& strDec)
+{
+	char* temp		= nullptr;
+	int src_length	= 0;
+
+	strDec.Empty();
+
+#ifdef UNICODE
+	char* temp1 = new char[(src_length = lstrlen(src)) +1];
+	temp = temp1;
+	while(*(temp1++) = (char)*(src++));
+#else
+	temp = (char*)src;
+	src_length = lstrlen(src);
+	//t = strDec.GetBuffer(src_length/2 + 1);
+#endif
+	int i=0;
+	for(; i < src_length / 2; ++i)
+	{
+		temp[i] = DOUBLECHARTOVALUE(temp + 2 * i);
+	}
+	temp[i] = 0;
+
+#ifdef UNICODE
+	int iLen	= 0;
+	WCHAR* wh	= nullptr;
+
+	MbcsToUnicode(temp, &wh, iLen);
+
+	strDec = wh;
+	delete[] wh;
+	delete[] temp;
+#else
+	strDec.ReleaseBuffer();
+#endif
+
+	return strDec;
+}
+
+CString& StrToUtf8Hex(const TCHAR* src, CString& strDec)
+{
+	char* t			= nullptr;
+	WCHAR* temp		= nullptr;
+	int src_length	= 0;
+
+	strDec.Empty();
+
+#ifndef UNICODE
+	MbcsToUnicode(src, &temp, src_length);
+#else
+	temp = (TCHAR*)src;
+#endif
+
+	UnicodeToUtf8(temp, &t, src_length);
+	src_length -= 1;
+
+	for(int i = 0; i < src_length; ++i)
+	{
+		TCHAR tc[3] = {0, 0, 0};
+		VALUETODOUBLECHAR(tc, t[i]);
+		strDec += tc;
+	}
+
+#ifndef UNICODE
+	delete[] temp;
+#endif
+	delete[] t;
+
+	return strDec;
+}
+
+CString& HexUtf8ToStr(const TCHAR* src, CString& strDec)
+{
+	char* temp		= nullptr;
+	WCHAR* pwsz		= nullptr;
+	int iLen		= 0;
+	int src_length	= 0;
+
+	strDec.Empty();
+
+#ifdef UNICODE
+	char* temp1	= new char[(src_length = lstrlen(src)) +1];
+	temp		= temp1;
+
+	while(*(temp1++) = (char)*(src++));
+#else
+	temp		= (char*)src;
+	src_length	= lstrlen(src);
+#endif
+	int i=0;
+	for(; i < src_length / 2; ++i)
+	{
+		temp[i] = DOUBLECHARTOVALUE(temp + 2*i);
+	}
+
+	temp[i] = 0;
+
+	Utf8ToUnicode(temp, &pwsz, iLen);
+
+#ifdef UNICODE
+	strDec = pwsz;
+	delete[] temp;
+#else
+	char* psz = nullptr;
+	UnicodeToMbcs(pwsz, &psz, iLen);
+
+	strDec = psz;
+	delete[] psz;
+#endif
+	delete[] pwsz;
+
+	return strDec;
+}
+
+CString GetSystemErrorDesc(DWORD dwCode)
+{
+	CString msg;
+	LPTSTR lpMsgBuf;
+
+	if(::FormatMessage(
+							FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+							nullptr,
+							dwCode,
+							MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+							(LPTSTR)&lpMsgBuf,
+							0,
+							nullptr
+						))
+	{
+		msg = lpMsgBuf;
+		::LocalFree(lpMsgBuf);
+	}
+
+	return msg;
+}
+
+BOOL SplitStr(LPCTSTR pszSrc, vector<CString>& vtItem, LPCTSTR pszSepectors, LPCTSTR pszQMarks)
+{
+	vtItem.clear();
+
+	CString strQMarks		= pszQMarks;
+	CString strSepectors	= pszSepectors;
+
+	if(strSepectors.IsEmpty())
+		strSepectors = _T(" ");
+
+	if(!strQMarks.IsEmpty())
+		if(strQMarks.FindOneOf(strSepectors) != -1)
+			return FALSE;
+
+	BOOL bRetVal	= TRUE;
+	CString strSrc	= pszSrc;
+
+	while(!strSrc.Trim(strSepectors).IsEmpty())
+	{
+		CString strItem;
+
+		int iSrcLen	= strSrc.GetLength();
+		int iPos1	= strSrc.FindOneOf(strSepectors);
+		int iPos2	= !strQMarks.IsEmpty() ? strSrc.FindOneOf(strQMarks) : -1;
+		int iPos3	= -1;
+
+		if(iPos1 == -1 && iPos2 == -1)
+			strItem = strSrc;
+		else if(iPos1 != -1 && (iPos1 < iPos2 || iPos2 == -1))
+			strItem = strSrc.Left(iPos1);
+		else	// (iPos1 > iPos2 || iPos1 == -1)
+		{
+			TCHAR tc	= strSrc[iPos2];
+			iPos3		= strSrc.Find(tc, iPos2 + 1);
+			if(iPos3 != -1)
+				strItem = strSrc.Mid(iPos2 + 1, iPos3 - iPos2 - 1);
+			else
+			{
+				vtItem.clear();
+				bRetVal = FALSE;
+				break;
+			}
+		}
+
+		vtItem.push_back(strItem);
+
+		strSrc = strSrc.Right(iPos3 == -1 ? (iSrcLen - (iPos1 == -1 ? strItem.GetLength() : iPos1 + 1)) : (iSrcLen - iPos3 - 1));
+	}
+
+	return bRetVal;
+}
+
+CString ExtractFileName(LPCTSTR lpszFullFileName)
+{
+	CString strPath = lpszFullFileName;
+	strPath.Trim();
+
+	if(!strPath.IsEmpty())
+	{
+		int iLen		= strPath.GetLength();
+		int iLastSep	= strPath.ReverseFind(PATH_SEPARATOR_CHAR);
+
+		if(iLastSep != -1)
+			strPath		= strPath.Right(iLen - 1 - iLastSep);
+	}
+	
+	return strPath;
+}
+
+CString ExtractPath(LPCTSTR lpszFullFileName)
+{
+	CString strPath = lpszFullFileName;
+	strPath.Trim();
+
+	if(strPath.IsEmpty())
+		return PATH_SEPARATOR;
+
+	int iLen		= strPath.GetLength();
+	int iLastSep	= strPath.ReverseFind(PATH_SEPARATOR_CHAR);
+	int iLastDot	= strPath.ReverseFind(FILE_EXTEND_SEPARATOR_CHAR);
+
+	if(iLastSep == -1 && iLastDot == -1)
+		strPath.Append(PATH_SEPARATOR);
+	else if(iLastSep == -1 && iLastDot != -1)
+		strPath = PATH_SEPARATOR;
+	else if(iLastSep > iLastDot)
+	{
+		if(iLastSep < iLen)
+			strPath.Append(PATH_SEPARATOR);
+	}
+	else
+	{
+		strPath = strPath.Left(iLastSep + 1);
+	}
+
+	return strPath;
+}
+
+CString ExtractModulePath(HMODULE hModule)
+{
+	CString strCurPath;
+	LPTSTR lpszCurPath = strCurPath.GetBuffer(MAX_PATH);
+
+	BOOL isOK = ::GetModuleFileName(hModule, lpszCurPath, MAX_PATH);
+	strCurPath.ReleaseBuffer();
+
+	if(isOK)
+	{
+		strCurPath = ::ExtractPath(strCurPath);
+		ASSERT(!strCurPath.IsEmpty());
+	}
+
+	return strCurPath;
+}
+
+BOOL RunProcess(LPCTSTR szFileName, LPCTSTR cmdline/* = nullptr*/, BOOL bHide /* = TRUE */, LPCTSTR dir /* =  nullptr*/, BOOL bWait /* = TRUE */, DWORD dwWaitTime /* = INFINITE */)
+{
+	LPCTSTR process_dir;
+	if (dir == nullptr || _tcslen(dir) == 0)
+		process_dir = nullptr;
+	else
+		process_dir = dir;
+
+	LPCTSTR process_name;
+	if (szFileName == nullptr || _tcslen(szFileName) == 0)
+		process_name = nullptr;
+	else
+		process_name = szFileName;
+
+	STARTUPINFO si;
+	ZeroMemory(&si, sizeof(si));
+	si.cb = sizeof(si);
+
+	DWORD dwCreationFlags = 0;
+	if (bHide)
+	{
+		si.wShowWindow = SW_HIDE;
+#ifndef _WIN32_WCE
+		dwCreationFlags = CREATE_NO_WINDOW;
+#endif
+	}
+
+	PROCESS_INFORMATION pi;
+	ZeroMemory(&pi, sizeof(pi));
+
+	// Start the child process
+	CString strCmd(cmdline);
+	LPTSTR pszcmd = (LPTSTR)(LPCTSTR)strCmd;
+
+	BOOL bRet = CreateProcess(
+								process_name,
+								pszcmd,					// Command line. 
+								nullptr,				// Process handle not inheritable. 
+								nullptr,				// Thread handle not inheritable. 
+								FALSE,					// Set handle inheritance to FALSE. 
+								dwCreationFlags,		// No creation flags. 
+								nullptr,				// Use parent's environment block. 
+								(LPTSTR)process_dir,	// Use parent's starting directory. 
+								&si,					// Pointer to STARTUPINFO structure.
+								&pi
+							);
+
+	if(bRet)
+	{
+		if(bWait)
+			bRet = (::WaitForSingleObject(pi.hProcess, dwWaitTime) != WAIT_FAILED) ? TRUE : FALSE;
+
+		::CloseHandle(pi.hProcess);
+		::CloseHandle(pi.hThread);
+	}
+
+	return bRet;
+}
+
+BOOL ShellRunExe(LPCTSTR lpszPath, LPCTSTR lpszParams, int iShow, HANDLE* phProcess, BOOL bWait, DWORD dwWaitTime)
+{
+	CString strPath = lpszPath;
+	strPath.Trim();
+
+	ASSERT(strPath.GetLength() > 4 && strPath.Right(4).CompareNoCase(EXE_FILE_EXTEND_NAME) == 0);
+
+#ifdef _WIN32_WCE
+	if(strPath.GetAt(0) != PATH_SEPARATOR_CHAR)
+#else
+	if(strPath.GetAt(1) != DISK_SYMBLE_CHAR)
+#endif
+	{
+		CString strCurPath = ExtractModulePath();
+		strPath = strCurPath + strPath;
+	}
+
+	SHELLEXECUTEINFO info = {0};
+
+	info.cbSize			= sizeof(SHELLEXECUTEINFO);
+	info.lpFile			= strPath;
+	info.fMask			= SEE_MASK_FLAG_NO_UI;
+	info.nShow			= iShow;
+	info.lpParameters	= lpszParams;
+	
+	if(phProcess || bWait)
+		info.fMask		|= SEE_MASK_NOCLOSEPROCESS;
+
+	BOOL isOK = FALSE;
+
+	if(::ShellExecuteEx(&info))
+	{
+		if(phProcess)
+			*phProcess = info.hProcess;
+
+		if(bWait)
+		{
+			isOK = (::WaitForSingleObject(info.hProcess, dwWaitTime) != WAIT_FAILED) ? TRUE : FALSE;
+			::CloseHandle(info.hProcess);
+		}
+		else
+			isOK = TRUE;
+	}
+
+	return isOK;
+}
+
+void WriteLog(LPCTSTR pszLogFileName, LPCTSTR pszLog)
+{
+#ifdef _UNICODE
+	USES_CONVERSION;
+#endif
+
+	HANDLE hLogFile = ::CreateFile(pszLogFileName, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
+	if(hLogFile != INVALID_HANDLE_VALUE)
+		::SetFilePointer(hLogFile, 0, 0, FILE_END);
+	else
+		return;
+
+	DWORD dwSize;
+	SYSTEMTIME st;
+	GetLocalTime(&st);
+	CString strLog;
+	strLog.Format(_T("[%02d-%02d %02d:%02d:%02d.%03d]  %s\r\n"), st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, pszLog);
+
+#ifdef _UNICODE
+	LPSTR lpszLog = T2A((LPTSTR)(LPCTSTR)strLog);
+	::WriteFile(hLogFile, lpszLog, (DWORD)::strlen(lpszLog), &dwSize, nullptr);
+#else
+	::WriteFile(hLogFile, strLog, strLog.GetLength(), &dwSize, nullptr);
+#endif
+
+	::CloseHandle(hLogFile);
+}
+
+BOOL FindProcess(LPCTSTR pszProcessName)
+{
+	BOOL isOK		= FALSE;
+	HANDLE hTool	= ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+	if(hTool != INVALID_HANDLE_VALUE)
+	{
+		PROCESSENTRY32 pe32;
+		pe32.dwSize = sizeof(PROCESSENTRY32);
+
+		if(::Process32First(hTool, &pe32))
+		{
+			do
+			{
+				if(_tcsicmp(pszProcessName, pe32.szExeFile) == 0)
+				{
+					isOK = TRUE;
+					break;
+				}
+
+			} while(::Process32Next(hTool, &pe32));
+		}
+
+		VERIFY(::CloseToolhelp32Snapshot(hTool));
+	}
+
+	return isOK;
+}
+
+HANDLE FindProcessHandle(LPCTSTR pszProcessName, DWORD dwDesiredAccess, BOOL bInheritHandle)
+{
+	HANDLE hProc	= nullptr;
+	HANDLE hTool	= ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+	if(hTool != INVALID_HANDLE_VALUE)
+	{
+		PROCESSENTRY32 pe32;
+		pe32.dwSize = sizeof(PROCESSENTRY32);
+
+		if(::Process32First(hTool, &pe32))
+		{
+			do
+			{
+				if(_tcsicmp(pszProcessName, pe32.szExeFile) == 0)
+				{
+					hProc = ::OpenProcess(dwDesiredAccess, bInheritHandle, pe32.th32ProcessID);
+					break;
+				}
+
+			} while(::Process32Next(hTool, &pe32));
+		}
+
+		VERIFY(::CloseToolhelp32Snapshot(hTool));
+	}
+
+	return hProc;
+}
+
+BOOL FindRunningProcessesInfo(ProcessInfoMap& infoMap)
+{
+	infoMap.Clear();
+
+	HANDLE hProc	= nullptr;
+	HANDLE hTool	= ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+	if(hTool != INVALID_HANDLE_VALUE)
+	{
+		PROCESSENTRY32 pe32;
+		pe32.dwSize = sizeof(PROCESSENTRY32);
+
+		if(::Process32First(hTool, &pe32))
+		{
+			do
+			{
+				PROCESSENTRY32* ppe32 = new PROCESSENTRY32;
+				memcpy(ppe32, &pe32, sizeof(PROCESSENTRY32));
+				infoMap[pe32.th32ProcessID] = ppe32;
+			} while(::Process32Next(hTool, &pe32));
+		}
+
+		VERIFY(::CloseToolhelp32Snapshot(hTool));
+	}
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+#ifndef _WIN32_WCE
+BOOL FindProcessEx(LPCTSTR pszProcessName)
+{
+	BOOL bRet = FALSE;
+
+	DWORD aProcesses[1024], cbNeeded, cProcesses;
+
+	if (::EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
+	{
+		cProcesses = cbNeeded / sizeof(DWORD);
+
+		for (DWORD i = 0; i < cProcesses; i++)
+		{
+			HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
+
+			if (hProcess)
+			{
+				HMODULE	hMod;
+				DWORD	cbNeeded;
+				if (::EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
+				{
+					TCHAR szProcessName[MAX_PATH] = {0};
+					if(::GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName)))
+					{
+						if(_tcsicmp(szProcessName, pszProcessName) == 0)
+						{
+							DWORD dwExitCode = 0;
+							if(::GetExitCodeProcess(hProcess, &dwExitCode) && dwExitCode == STILL_ACTIVE)
+							{
+								bRet = TRUE;
+								break;
+							}
+						}
+					}
+				}
+				::CloseHandle( hProcess );
+			}
+		}
+	}
+
+	return bRet;
+}
+
+CString GetIniString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpFileName, DWORD dwSize)
+{
+	CString strValue;
+	LPTSTR pszBuffer = strValue.GetBuffer(dwSize);
+	::GetPrivateProfileString(lpAppName, lpKeyName, _T(""), pszBuffer, dwSize, lpFileName);
+	strValue.ReleaseBuffer();
+	strValue.Trim();
+	return strValue;
+}
+
+BOOL SetCurrentPathToModulePath(HMODULE hModule)
+{
+	TCHAR szPath[MAX_PATH];
+	if(::GetModuleFileName(hModule, szPath, MAX_PATH))
+	{
+		TCHAR drive[MAX_PATH], dir[MAX_PATH], fname[MAX_PATH], ext[MAX_PATH];
+		_tsplitpath(szPath, drive, dir, fname, ext);
+		lstrcpy(szPath, drive);
+		lstrcat(szPath, dir);
+
+		return ::SetCurrentDirectory(szPath);
+	}
+
+	return FALSE;
+}
+#endif
+
+struct TProcWnd
+{
+	DWORD	dwProcID;
+	LPCTSTR lpszClassName;
+	HWND	hWnd;
+};
+
+BOOL CALLBACK ProcessMainWindowEnumFunc(HWND hwnd, LPARAM lParam)
+{
+	TProcWnd* ppw = (TProcWnd*)lParam;
+
+	DWORD dwProcID;
+	::GetWindowThreadProcessId(hwnd, &dwProcID);
+
+	if(dwProcID == ppw->dwProcID)
+	{
+		while(TRUE)
+		{
+			HWND hwParent = ::GetParent(hwnd);
+
+			if(hwParent == nullptr)
+			{
+				if(ppw->lpszClassName == nullptr)
+				{
+					ppw->hWnd = hwnd;
+					return FALSE;
+				}
+				else
+				{
+					int nMaxCount = MAX_PATH - 1;
+					TCHAR szName[MAX_PATH] = {0};
+
+					if(::GetClassName(hwnd, szName, nMaxCount))
+					{
+						if(_tcscmp(szName, ppw->lpszClassName) == 0)
+						{
+							ppw->hWnd = hwnd;
+							return FALSE;
+						}
+					}
+				}
+
+				break;
+			}
+			else
+				hwnd = hwParent;
+		}
+	}
+
+	return TRUE;
+}
+
+HWND FindProcessMainWindow(DWORD dwProcID, LPCTSTR lpszWndClassName)
+{
+	if(dwProcID == 0)
+		dwProcID = ::GetCurrentProcessId();
+
+	ASSERT(dwProcID != 0);
+
+	TProcWnd pw;
+	pw.dwProcID			= dwProcID;
+	pw.lpszClassName	= lpszWndClassName;
+	pw.hWnd				= nullptr;
+
+	::EnumWindows(ProcessMainWindowEnumFunc, (LPARAM)&pw);
+
+	return pw.hWnd;
+}
+
+HWND FindProcessMainWindow(HANDLE hProcess, LPCTSTR lpszWndClassName)
+{
+	DWORD dwProcID = (hProcess == nullptr) ? ::GetCurrentProcessId() : ::GetProcessId(hProcess);
+
+	if(dwProcID != 0)
+		return FindProcessMainWindow(dwProcID, lpszWndClassName);
+
+	return nullptr;
+}
+
+BOOL CALLBACK CloseWindowEnumFunc(HWND hwnd, LPARAM lParam)
+{
+	DWORD dwProcID;
+	::GetWindowThreadProcessId(hwnd, &dwProcID);
+
+	if(dwProcID == (DWORD)lParam)
+		::PostMessage(hwnd, WM_CLOSE, 0, 0);
+
+	return TRUE;
+}
+
+BOOL TerminateProcessFairily(HANDLE hProcess, DWORD dwWait)
+{
+	DWORD dwProcID = ::GetProcessId(hProcess);
+
+	if(dwProcID != 0)
+	{
+		VERIFY(::EnumWindows(CloseWindowEnumFunc, (LPARAM)dwProcID));
+
+		if(!::MsgWaitForSingleObject(hProcess, dwWait))
+			return ::TerminateProcess(hProcess, -1);
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+#ifdef _AFX
+CString SecondToTimeStr(DWORD dwSeconds, BOOL bDayOnly)
+{
+	CTime tm(dwSeconds);
+	LPCTSTR pszFormat = bDayOnly ? _T("%Y-%m-%d") : _T("%Y-%m-%d %H:%M:%S");
+	return tm.Format(pszFormat);
+}
+#endif
+
+BOOL GetRegistryValue(HKEY hRoot, LPCTSTR wcSubKey, LPCTSTR wcName, LPBYTE pValue, DWORD* pdwSize, DWORD* pdwType)
+{
+	DWORD result = ERROR_INVALID_DATA;
+
+	CRegKey reg;
+
+	result = reg.Create(hRoot, wcSubKey, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ);
+	if(result  == ERROR_SUCCESS)
+		result = reg.QueryValue(wcName, pdwType, pValue, pdwSize);
+	
+
+	BOOL isOK = (result == ERROR_SUCCESS);
+
+	if(!isOK)
+	{
+		*pValue		= 0;
+		*pdwSize	= 0;
+		*pdwType	= REG_NONE;
+	}
+
+	return isOK;
+}
+
+BOOL SetRegistryValue(HKEY hRoot, LPCTSTR wcSubKey, LPCTSTR wcName, LPBYTE pValue, DWORD dwSize, DWORD dwType)
+{
+	DWORD result = ERROR_INVALID_DATA;
+
+	CRegKey reg;
+
+	result = reg.Create(hRoot, wcSubKey);
+	if(result  == ERROR_SUCCESS)
+		result = reg.SetValue(wcName, dwType, pValue, dwSize);
+
+	return (result == ERROR_SUCCESS);
+}

+ 171 - 0
source/hook/hp-src/FuncHelper.h

@@ -0,0 +1,171 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+#include "GeneralHelper.h"
+
+#include <tlhelp32.h>
+#include <malloc.h>
+
+#define PATH_SEPARATOR				_T("\\")
+#define PATH_SEPARATOR_CHAR			_T('\\')
+#define FILE_EXTEND_SEPARATOR		_T(".")
+#define FILE_EXTEND_SEPARATOR_CHAR	_T('.')
+#define DISK_SYMBLE					_T(":")
+#define DISK_SYMBLE_CHAR			_T(':')
+#define EXE_FILE_EXTEND_NAME		_T(".exe")
+
+enum EnCodePage
+{
+	XCP_ACP		= CP_ACP,
+	XCP_GB2312	= 936,
+#ifdef _WIN32_WCE
+	XCP_BIG5	= CP_ACP,
+#else
+	XCP_BIG5	= 950,
+#endif
+	XCP_GBK		= XCP_GB2312,
+	XCP_UTF7	= CP_UTF7,
+	XCP_UTF8	= CP_UTF8,
+};
+
+/************************************* 字符操作 *************************************/
+
+// 把字符转换成其表示的值: 如字符 'F' 转换成 数值 15
+#define CHARTOVALUE(c)				(c <= '9' ? c - '0' : (c <= 'F' ? c - 'A' + 0x0A : c - 'a' + 0X0A))
+// 把双字符转换成其表示的值: 如字符 '1F' 转换成 数值 31
+#define DOUBLECHARTOVALUE(pc)		(((CHARTOVALUE(*(pc))) << 4) | (CHARTOVALUE(*(pc + 1))))
+
+// 把数值转换成其十六进制字符: 如数值 15 转换成 字符 'F'
+#define VALUETOCHAR(n)				(n <= 9 ? n + '0' : (n <= 'F' ? n + 'A' - 0X0A : n + 'a' - 0X0A))
+// 把数值字符转换成其两个十六进制字符: 如数值 11 转换成 字符 '0B'
+#define VALUETODOUBLECHAR(pc, n)	{*(pc) = VALUETOCHAR((n >> 4)); *((pc) + 1) = VALUETOCHAR((n & 0X0F));}
+
+// 把双字符转换成其表示的值: 如字符 '1F' 转换成 数值 31
+BYTE DoubleCharToByte(LPCTSTR psValue);
+// 把数值字符转换成其两个十六进制字符: 如数值 11 转换成 字符 '0B'
+LPTSTR ByteToDoubleChar(BYTE b, LPTSTR des);
+// 把十六进制转换成其表示的值: 如字符 '601F' 转换成 数值 24607
+UINT HexStrToInt(LPCTSTR pHexText, int len = -1);
+// 把十进制转换成其表示的值: 如字符 '0000024607' 转换成 数值 24607
+UINT DecStrToInt(LPCTSTR pDecText, int len = -1);
+// 把数值换成其十六进制字符串表示的值: 如数值 24607 转换成 字符 '601F'
+CString& IntToHexStr(CString& dest, UINT v, int len = -1);
+// 把数值换成其十进制字符串表示的值: 如数值 24607 转换成 字符 '24607'
+CString& IntToDecStr(CString& dest, UINT v, int len = -1);
+// 把十六进制表示的地址改为十进制表示的地址: 如 "000C35CE" 转换成 '0000800236'
+CString& HexAddrToDecAddr(CString& dest, LPCTSTR src, int destlen = 10, int srclen = -1);
+// 把十进制表示的地址改为十六进制表示的地址: 如 "0000800236" 转换成 '000C35CE'
+CString& DecAddrToHexAddr(CString& dest, LPCTSTR src, int destlen = 8, int srclen = -1);
+
+// Code Page Name -> Code Page Value
+EnCodePage GetCodePageByName(LPCTSTR lpszCodePageName);
+
+// MBCS -> UNICODE
+BOOL MbcsToUnicode(const char* pszInString, WCHAR** ptrOutWStr, int& nSizeCount);
+// UNICODE -> MBCS
+BOOL UnicodeToMbcs(const WCHAR* pwzInString, char** ptrOutStr, int& nSizeCount);
+// UTF8 -> UNICODE
+BOOL Utf8ToUnicode(const char* pszInString, WCHAR** ptrOutWStr, int& nSizeCount);
+// UNICODE -> UTF8
+BOOL UnicodeToUtf8(const WCHAR* pwzInString, char** ptrOutStr, int& nSizeCount);
+// CP_XXX -> UNICODE
+BOOL CPToUni(const char* pszInString, WCHAR** ptrOutWStr, unsigned int nCodePage, int& nSizeCount);
+// UNICODE -> CP_XXX
+BOOL UniToCP(const WCHAR* pwzInString, char** ptrOutStr, unsigned int nCodePage, int& nSizeCount);
+
+// 把字节数组转换成16进制字符串
+int BytesToHex(const BYTE* pBytes, int nLength, LPTSTR* lpszDest);
+// 把16进制字符串转换成字节数组
+int HexToBytes(LPCTSTR lpszHex, BYTE** ppBytes, int* pnLength);
+
+// 把普通字符串转换成16进制字符串
+CString& StrToHex(const TCHAR* src, CString& des);
+// 把16进制字符串转换成普通字符串
+CString& HexToStr(const TCHAR* src, CString& des);
+// 把普通字符串转换成UTF8字符串, 然后再把该UTF8字符串转换成16进制字符串
+CString& StrToUtf8Hex(const TCHAR* src, CString& strDec);
+// 把16进制字符串转换成UTF8字符串, 然后再把该UTF8字符串转换成普通字符串
+CString& HexUtf8ToStr(const TCHAR* src, CString& strDec);
+
+// 取得系统错误代码的描述信息
+CString GetSystemErrorDesc(DWORD dwCode);
+
+// 分隔字符串
+BOOL SplitStr(LPCTSTR pszSrc, vector<CString>& vtItem, LPCTSTR pszSepectors = nullptr, LPCTSTR pszQMarks = nullptr);
+
+// 提取文件名称
+CString ExtractFileName(LPCTSTR lpszFullFileName);
+// 提取文件路径
+CString ExtractPath(LPCTSTR lpszFullFileName);
+// 提取文件路径
+CString ExtractPath(LPCTSTR lpszFullFileName);
+// 提取当前模块路径
+CString ExtractModulePath(HMODULE hModule = nullptr);
+
+// 启动进程
+BOOL RunProcess(LPCTSTR sFileName, LPCTSTR cmdline = nullptr, BOOL bHide = TRUE, LPCTSTR dir = nullptr, BOOL bWait = TRUE, DWORD dwWaitTime = INFINITE);
+BOOL ShellRunExe(LPCTSTR lpszPath, LPCTSTR lpszParams = nullptr, int iShow = SW_SHOWNORMAL, HANDLE* phProcess = nullptr, BOOL bWait = FALSE, DWORD dwWaitTime = INFINITE);
+
+// 查找进程
+BOOL FindProcess(LPCTSTR pszProcessName);
+
+// 查找进程句柄
+HANDLE FindProcessHandle(LPCTSTR pszProcessName, DWORD dwDesiredAccess = PROCESS_QUERY_INFORMATION, BOOL bInheritHandle = FALSE);
+
+typedef map<DWORD, PROCESSENTRY32*>									ProcessInfos;
+typedef MapWrapper<ProcessInfos, PtrMap_Cleaner<ProcessInfos>>		ProcessInfoMap;
+
+// 查找当前运行的信息
+BOOL FindRunningProcessesInfo(ProcessInfoMap& infoMap);
+
+// 查找进程的主窗口
+HWND FindProcessMainWindow(DWORD dwProcID, LPCTSTR lpszClassName = nullptr);
+// 查找进程的主窗口
+HWND FindProcessMainWindow(HANDLE hProcess, LPCTSTR lpszClassName = nullptr);
+
+BOOL TerminateProcessFairily(HANDLE hProcess, DWORD dwWait = INFINITE);
+
+// 简单记录日志
+void WriteLog(LPCTSTR pszLogFileName, LPCTSTR pszLog);
+
+#ifndef _WIN32_WCE
+	// 设置当前路径
+	BOOL SetCurrentPathToModulePath(HMODULE hModule = nullptr);
+	// 查找进程
+	BOOL FindProcessEx(LPCTSTR pszProcessName);
+	// 读取 INI 配置
+	CString GetIniString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpFileName, DWORD dwSize);
+#endif
+
+#ifdef _AFX
+	// 秒转换成时间字符串
+	CString SecondToTimeStr(DWORD dwSeconds, BOOL bDayOnly = FALSE);
+#endif
+
+// 设置注册表项
+BOOL GetRegistryValue(HKEY hRoot, LPCTSTR wcSubKey, LPCTSTR wcName, LPBYTE pValue, DWORD* pdwSize, DWORD* pdwType);
+// 获取注册表项
+BOOL SetRegistryValue(HKEY hRoot, LPCTSTR wcSubKey, LPCTSTR wcName, LPBYTE pValue, DWORD dwSize, DWORD dwType);

+ 26 - 0
source/hook/hp-src/GeneralHelper.cpp

@@ -0,0 +1,26 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "stdafx.h"
+#include "GeneralHelper.h"

+ 402 - 0
source/hook/hp-src/RWLock.cpp

@@ -0,0 +1,402 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *		http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "StdAfx.h"
+#include "RWLock.h"
+
+////////////////////////////////// CSWMR Functions ////////////////////////////////////
+
+CSWMR::CSWMR()
+: m_smRead			(MAXLONG)
+, m_smWrite			(1)
+, m_nWaitingReaders	(0)
+, m_nWaitingWriters	(0)
+, m_nActive			(0)
+{
+
+}
+
+CSWMR::~CSWMR()
+{
+	ASSERT(m_nWaitingReaders == 0);
+	ASSERT(m_nWaitingWriters == 0);
+	ASSERT(m_nActive		 == 0);
+}
+
+VOID CSWMR::WaitToRead()
+{
+	BOOL fResourceWritePending;
+
+	{
+		CSpinLock locallock(m_cs);
+
+		fResourceWritePending = (m_nWaitingWriters || (m_nActive < 0));
+
+		if(fResourceWritePending)
+			++m_nWaitingReaders;
+		else
+			++m_nActive;
+	}
+
+	if(fResourceWritePending)
+		m_smRead.Wait();
+}
+
+VOID CSWMR::WaitToWrite()
+{
+	BOOL fResourceOwned;
+
+	{
+		CSpinLock locallock(m_cs);
+
+		fResourceOwned = (m_nActive != 0);
+
+		if(fResourceOwned)
+			++m_nWaitingWriters;
+		else
+			m_nActive = -1;
+	}
+
+	if(fResourceOwned)
+		m_smWrite.Wait();
+}
+
+VOID CSWMR::Done()
+{
+	CSEM* pSem  = nullptr;
+	LONG lCount = 1;
+
+	{
+		CSpinLock locallock(m_cs);
+
+		if(m_nActive > 0)
+			--m_nActive;
+		else
+			++m_nActive;
+
+		if(m_nActive == 0)
+		{
+			if(m_nWaitingWriters > 0)
+			{
+				m_nActive = -1;
+				--m_nWaitingWriters;
+				pSem = &m_smWrite;
+			}
+			else if(m_nWaitingReaders > 0)
+			{
+				m_nActive = m_nWaitingReaders;
+				m_nWaitingReaders = 0;
+				pSem = &m_smRead;
+				lCount = m_nActive;
+			}
+		}
+	}
+
+	if(pSem != nullptr)
+		pSem->Release(lCount);
+}
+
+//////////////////////////////// CRWLock Functions //////////////////////////////////
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WS08
+
+CSlimRWLock::CSlimRWLock()
+	: m_nActive			(0)
+	, m_nReadCount		(0)
+	, m_dwWriterTID		(0)
+{
+
+}
+
+CSlimRWLock::~CSlimRWLock()
+{
+	ASSERT(m_nActive	 == 0);
+	ASSERT(m_nReadCount	 == 0);
+	ASSERT(m_dwWriterTID == 0);
+}
+
+VOID CSlimRWLock::WaitToRead()
+{
+	BOOL bWait = FALSE;
+
+	{
+		CSpinLock locallock(m_cs);
+
+		if(m_nActive > 0)
+			++m_nActive;
+		else if(m_nActive == 0)
+		{
+			if(m_smLock.TryWaitToRead())
+			{
+				++m_nReadCount;
+				++m_nActive;
+			}
+			else
+				bWait = TRUE;
+		}
+		else if(!IsOwner())
+			bWait = TRUE;
+	}
+
+	if(bWait)
+	{
+		m_smLock.WaitToRead();
+
+		CSpinLock locallock(m_cs);
+		{
+			++m_nReadCount;
+			++m_nActive;
+		}
+	}
+}
+
+VOID CSlimRWLock::WaitToWrite()
+{
+	BOOL bWait = FALSE;
+
+	{
+		CSpinLock locallock(m_cs);
+
+		if(m_nActive > 0)
+			bWait = TRUE;
+		else if(m_nActive == 0)
+		{
+			if(m_smLock.TryWaitToWrite())
+			{
+				SetOwner();
+				--m_nActive;
+			}
+			else
+				bWait = TRUE;
+		}
+		else
+		{
+			if(IsOwner())
+				--m_nActive;
+			else
+				bWait = TRUE;
+		}
+	}
+
+	if(bWait)
+	{
+		m_smLock.WaitToWrite();
+
+		SetOwner();
+		--m_nActive;
+	}
+}
+
+VOID CSlimRWLock::ReadDone()
+{
+	ASSERT(m_nActive != 0);
+
+	if(m_nActive > 0)
+	{
+		ASSERT(m_nReadCount > 0);
+
+		CSpinLock locallock(m_cs);
+
+		if(--m_nActive == 0)
+		{
+			for(; m_nReadCount > 0; --m_nReadCount)
+				m_smLock.ReadDone();
+		}
+	}
+	else
+		ASSERT(IsOwner());
+}
+
+VOID CSlimRWLock::WriteDone()
+{
+	ASSERT(m_nActive < 0);
+
+	CSpinLock locallock(m_cs);
+
+	if(++m_nActive == 0)
+	{
+		DetachOwner();
+		m_smLock.WriteDone();
+	}
+	else
+		ASSERT(IsOwner());
+}
+
+#endif
+
+CSEMRWLock::CSEMRWLock()
+: m_smRead			(MAXLONG)
+, m_smWrite			(1)
+, m_nWaitingReaders	(0)
+, m_nWaitingWriters	(0)
+, m_nActive			(0)
+, m_dwWriterTID		(0)
+{
+
+}
+
+CSEMRWLock::~CSEMRWLock()
+{
+	ASSERT(m_nActive	 == 0);
+	ASSERT(m_dwWriterTID == 0);
+}
+
+VOID CSEMRWLock::WaitToRead()
+{
+	BOOL bWait = FALSE;
+
+	{
+		CSpinLock locallock(m_cs);
+
+		if(m_nActive > 0)
+			++m_nActive;
+		else if(m_nActive == 0)
+		{
+			if(m_nWaitingWriters == 0)
+				++m_nActive;
+			else
+			{
+				++m_nWaitingReaders;
+				bWait = TRUE;
+			}
+		}
+		else
+		{
+			if(!IsOwner())
+			{
+				++m_nWaitingReaders;
+				bWait = TRUE;
+			}
+		}
+	}
+
+	if(bWait)
+	{
+		m_smRead.Wait();
+	}
+}
+
+VOID CSEMRWLock::WaitToWrite()
+{
+	BOOL bWait = FALSE;
+
+	{
+		CSpinLock locallock(m_cs);
+
+		if(m_nActive > 0)
+		{
+			++m_nWaitingWriters;
+			bWait = TRUE;
+		}
+		else if(m_nActive == 0)
+		{
+			--m_nActive;
+			SetOwner();
+		}
+		else
+		{
+			if(IsOwner())
+				--m_nActive;
+			else
+			{
+				++m_nWaitingWriters;
+				bWait = TRUE;
+			}
+		}
+	}
+
+	if(bWait)
+	{
+		m_smWrite.Wait();
+		SetOwner();
+	}
+}
+
+VOID CSEMRWLock::ReadDone()
+{
+	CSEM* pSem	 = nullptr;
+	LONG  lCount = 0;
+
+	ASSERT(m_nActive != 0);
+
+	if(m_nActive > 0)
+	{
+		CSpinLock locallock(m_cs);
+
+		if(--m_nActive == 0)
+			Done(&pSem, lCount);
+	}
+	else
+		ASSERT(IsOwner());
+
+	if(pSem != nullptr)
+		pSem->Release(lCount);
+}
+
+VOID CSEMRWLock::WriteDone()
+{
+	CSEM* pSem	 = nullptr;
+	LONG  lCount = 0;
+
+	{
+		ASSERT(m_nActive < 0);
+
+		CSpinLock locallock(m_cs);
+
+		if(++m_nActive == 0)
+		{
+			DetachOwner();
+			Done(&pSem, lCount);
+		}
+		else
+			ASSERT(IsOwner());
+	}
+
+	if(pSem != nullptr)
+		pSem->Release(lCount);
+}
+
+VOID CSEMRWLock::Done(CSEM** ppSem, LONG& lCount)
+{
+	ASSERT(m_nActive	 == 0);
+	ASSERT(m_dwWriterTID == 0);
+
+	if(m_nWaitingWriters > 0)
+	{
+		--m_nActive;
+		--m_nWaitingWriters;
+
+		lCount = 1;
+		*ppSem = &m_smWrite;
+	}
+	else if(m_nWaitingReaders > 0)
+	{
+		m_nActive			= m_nWaitingReaders;
+		m_nWaitingReaders	= 0;
+		lCount				= m_nActive;
+		*ppSem				= &m_smRead;
+	}
+}
+
+/////////////////////////////////// End of File /////////////////////////////////////

+ 418 - 0
source/hook/hp-src/RWLock.h

@@ -0,0 +1,418 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *		http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "CriticalSection.h"
+#include "Semaphore.h"
+
+class CSWMR
+{
+public:
+	VOID WaitToRead();
+	VOID WaitToWrite();
+	VOID ReadDone()  {Done();}
+	VOID WriteDone() {Done();}
+
+private:
+	VOID Done();
+
+public:
+	CSWMR();
+	~CSWMR();
+
+private:
+	CSWMR(const CSWMR&);
+	CSWMR operator = (const CSWMR&);
+
+private:
+	int m_nWaitingReaders;
+	int m_nWaitingWriters;
+	int m_nActive;
+
+	CSpinGuard	m_cs;
+	CSEM		m_smRead;
+	CSEM		m_smWrite;
+};
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WS08
+
+class CSlimLock
+{
+public:
+	VOID WaitToRead()		{::AcquireSRWLockShared(&m_lock);}
+	VOID WaitToWrite()		{::AcquireSRWLockExclusive(&m_lock);}
+	VOID ReadDone()			{::ReleaseSRWLockShared(&m_lock);}
+	VOID WriteDone()		{::ReleaseSRWLockExclusive(&m_lock);}
+	BOOL TryWaitToRead()	{return ::TryAcquireSRWLockShared(&m_lock);}
+	BOOL TryWaitToWrite()	{return ::TryAcquireSRWLockExclusive(&m_lock);}
+
+	SRWLOCK* GetObject()	{return &m_lock;}
+
+public:
+	CSlimLock()		{::InitializeSRWLock(&m_lock);}
+	~CSlimLock()	{}
+
+private:
+	CSlimLock(const CSlimLock&);
+	CSlimLock operator = (const CSlimLock&);
+
+private:
+	SRWLOCK m_lock;
+};
+
+class CSlimRWLock
+{
+public:
+	VOID WaitToRead();
+	VOID WaitToWrite();
+	VOID ReadDone();
+	VOID WriteDone();
+
+private:
+	BOOL IsOwner()		{return m_dwWriterTID == ::GetCurrentThreadId();}
+	VOID SetOwner()		{m_dwWriterTID = ::GetCurrentThreadId();}
+	VOID DetachOwner()	{m_dwWriterTID = 0;}
+
+public:
+	CSlimRWLock();
+	~CSlimRWLock();
+
+private:
+	CSlimRWLock(const CSlimRWLock&);
+	CSlimRWLock operator = (const CSlimRWLock&);
+
+private:
+	int m_nActive;
+	int m_nReadCount;
+	DWORD m_dwWriterTID;
+
+	CSpinGuard	m_cs;
+	CSlimLock	m_smLock;
+};
+
+#endif
+
+class CSEMRWLock
+{
+public:
+	VOID WaitToRead();
+	VOID WaitToWrite();
+	VOID ReadDone();
+	VOID WriteDone();
+
+private:
+	VOID Done			(CSEM** ppSem, LONG& lCount);
+	BOOL IsOwner()		{return m_dwWriterTID == ::GetCurrentThreadId();}
+	VOID SetOwner()		{m_dwWriterTID = ::GetCurrentThreadId();}
+	VOID DetachOwner()	{m_dwWriterTID = 0;}
+
+public:
+	CSEMRWLock();
+	~CSEMRWLock();
+
+private:
+	CSEMRWLock(const CSEMRWLock&);
+	CSEMRWLock operator = (const CSEMRWLock&);
+
+private:
+	int m_nWaitingReaders;
+	int m_nWaitingWriters;
+	int m_nActive;
+	DWORD m_dwWriterTID;
+
+	CSpinGuard	m_cs;
+	CSEM		m_smRead;
+	CSEM		m_smWrite;
+};
+
+template<class CLockObj> class CLocalReadLock
+{
+public:
+	CLocalReadLock(CLockObj& obj) : m_wait(obj) {m_wait.WaitToRead();}
+	~CLocalReadLock() {m_wait.ReadDone();}
+private:
+	CLocalReadLock(const CLocalReadLock&);
+	CLocalReadLock operator = (const CLocalReadLock&);
+private:
+	CLockObj& m_wait;
+};
+
+template<class CLockObj> class CLocalWriteLock
+{
+public:
+	CLocalWriteLock(CLockObj& obj) : m_wait(obj) {m_wait.WaitToWrite();}
+	~CLocalWriteLock() {m_wait.WriteDone();}
+private:
+	CLocalWriteLock(const CLocalWriteLock&);
+	CLocalWriteLock operator = (const CLocalWriteLock&);
+private:
+	CLockObj& m_wait;
+};
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WS08
+	typedef CSlimLock	CSimpleRWLock;
+#else
+	typedef CSWMR		CSimpleRWLock;
+#endif
+
+typedef CLocalReadLock<CSimpleRWLock>	CReadLock;
+typedef CLocalWriteLock<CSimpleRWLock>	CWriteLock;
+
+typedef CSEMRWLock						CRWLock;
+typedef CLocalReadLock<CRWLock>			CReentrantReadLock;
+typedef CLocalWriteLock<CRWLock>		CReentrantWriteLock;
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WS08
+
+class ICVCondition
+{
+public:
+	virtual BOOL Detect() = 0;
+
+public:
+	virtual ~ICVCondition() {}
+};
+
+class CCVCriSec
+{
+public:
+	CCVCriSec(CInterCriSec& cs)
+	: m_cs(cs)
+	{
+		::InitializeConditionVariable(&m_cv);
+	}
+
+	~CCVCriSec() {}
+
+	void WaitToRead(ICVCondition* pCondition)
+	{
+		Wait(pCondition);
+	}
+
+	void WaitToWrite(ICVCondition* pCondition)
+	{
+		Wait(pCondition);
+	}
+
+	void ReadDone()
+	{
+		Done();
+	}
+
+	void WriteDone()
+	{
+		Done();
+	}
+
+	void WakeUp()
+	{
+		::WakeConditionVariable(&m_cv);
+	}
+
+	void WakeUpAll()
+	{
+		::WakeAllConditionVariable(&m_cv);
+	}
+
+private:
+	void Wait(ICVCondition* pCondition)
+	{
+		ASSERT(pCondition);
+
+		m_cs.Lock();
+
+		while(!pCondition->Detect()) 
+			::SleepConditionVariableCS(&m_cv, m_cs.GetObject(), INFINITE);
+	}
+
+	void Done()
+	{
+		m_cs.Unlock();
+	}
+
+private:
+	CCVCriSec(const CCVCriSec& cs);
+	CCVCriSec operator = (const CCVCriSec& cs);
+
+private:
+	CInterCriSec&		m_cs;
+	CONDITION_VARIABLE	m_cv;
+};
+
+class CCVSlim
+{
+public:
+	CCVSlim(CSlimLock& cs)
+	: m_cs(cs)
+	{
+		::InitializeConditionVariable(&m_cv);
+	}
+
+	~CCVSlim() {}
+
+	void WaitToRead(ICVCondition* pCondition)
+	{
+		ASSERT(pCondition);
+
+		m_cs.WaitToRead();
+
+		while(!pCondition->Detect()) 
+			::SleepConditionVariableSRW(&m_cv, m_cs.GetObject(), INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED);
+	}
+
+	void WaitToWrite(ICVCondition* pCondition)
+	{
+		ASSERT(pCondition);
+
+		m_cs.WaitToWrite();
+
+		while(!pCondition->Detect())  
+			::SleepConditionVariableSRW(&m_cv, m_cs.GetObject(), INFINITE, 0);
+	}
+
+	void ReadDone()
+	{
+		m_cs.ReadDone();
+	}
+
+	void WriteDone()
+	{
+		m_cs.WriteDone();
+	}
+
+	void WakeUp()
+	{
+		::WakeConditionVariable(&m_cv);
+	}
+
+	void WakeUpAll()
+	{
+		::WakeAllConditionVariable(&m_cv);
+	}
+
+private:
+	CCVSlim(const CCVSlim& cs);
+	CCVSlim operator = (const CCVSlim& cs);
+
+private:
+	CSlimLock&			m_cs;
+	CONDITION_VARIABLE	m_cv;
+};
+
+template<class _Lock, class _Var> class CCVGuard
+{
+public:
+	void WaitForProduce()
+	{
+		m_cvP.WaitToWrite(m_pcdtProduce);
+	}
+
+	void WaitForConsume()
+	{
+		m_cvC.WaitToRead(m_pcdtConsume);
+	}
+
+	void ProduceDone()
+	{
+		m_cvP.WriteDone();
+	}
+
+	void WakeUpProduce()
+	{
+		m_cvP.WakeUp();
+	}
+
+	void ConsumeDone()
+	{
+		m_cvC.ReadDone();
+	}
+
+	void WakeUpConsume()
+	{
+		m_cvC.WakeUp();
+	}
+
+	void WakeUpAllConsumes()
+	{
+		m_cvC.WakeUpAll();
+	}
+
+public:
+	CCVGuard(ICVCondition* pcdtProduce, ICVCondition* pcdtConsume)
+	: m_cvP(m_cs)
+	, m_cvC(m_cs)
+	, m_pcdtProduce(pcdtProduce)
+	, m_pcdtConsume(pcdtConsume)
+	{
+		ASSERT(m_pcdtConsume && m_pcdtProduce);
+	}
+
+	~CCVGuard()	{}
+
+private:
+	CCVGuard(const CCVGuard& cs);
+	CCVGuard operator = (const CCVGuard& cs);
+
+private:
+	ICVCondition* m_pcdtProduce;
+	ICVCondition* m_pcdtConsume;
+
+	_Lock	m_cs;
+	_Var	m_cvP;
+	_Var	m_cvC;
+};
+
+template<class _GuardObj> class CConsumeLock
+{
+public:
+	CConsumeLock(_GuardObj& obj) : m_guard(obj) {m_guard.WaitForConsume();}
+	~CConsumeLock() {m_guard.ConsumeDone();}
+private:
+	CConsumeLock(const CConsumeLock&);
+	CConsumeLock operator = (const CConsumeLock&);
+private:
+	_GuardObj& m_guard;
+};
+
+template<class _GuardObj> class CProduceLock
+{
+public:
+	CProduceLock(_GuardObj& obj) : m_guard(obj) {m_guard.WaitForProduce();}
+	~CProduceLock() {m_guard.ProduceDone();}
+private:
+	CProduceLock(const CProduceLock&);
+	CProduceLock operator = (const CProduceLock&);
+private:
+	_GuardObj& m_guard;
+};
+
+typedef CCVGuard<CInterCriSec, CCVCriSec>	CCVGuardCS;
+typedef CCVGuard<CSlimLock, CCVSlim>		CCVGuardSRW;
+typedef CProduceLock<CCVGuardCS>			CProduceLockCS;
+typedef CConsumeLock<CCVGuardCS>			CConsumeLockCS;
+typedef CProduceLock<CCVGuardSRW>			CProduceLockSRW;
+typedef CConsumeLock<CCVGuardSRW>			CConsumeLockSRW;
+
+#endif

+ 99 - 0
source/hook/hp-src/SE.h

@@ -0,0 +1,99 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/******************************************************************************
+
+Module:  SE.h
+Notices: Copyright (c) 2006 Bruce Liang
+Purpose: 把结构化异常转换成 C++ 异常.
+Desc:
+		 1. 用 C++ 方式处理结构化异常
+
+Usage:
+		 1. 项目 -> 配置属性 -> C/C++ -> 代码生成 -> 启用 C++ 异常选择"否"
+		 2. 项目 -> 配置属性 -> C/C++ -> 命令行 -> 加入 "/EHac"
+		 3. 在每个线程的入口处调用: MapSEx2CppEx()
+		 4. 在要处理结构化异常的地方使用 try{...} catch(CSE se){...}
+
+Rule:	
+
+Example:	1. 见: TestSE 测试程序
+			2. 下面的代码片断
+			void ThreadFunc(PVOID pv)
+			{
+				// Must be called before any exceptions are raised
+				MapSEx2CppEx();
+
+				try
+				{
+					*(PBYTE)0 = 0;		// Accesss violation
+
+					int x = 0;
+					x = 5 / x;			// Division by zero
+				}
+				catch(CSE& se)
+				{
+					switch(se)
+					{
+					case EXCEPTION_ACCESS_VIOLATION:
+						// This code handles an access-violation exception
+						break;
+					case EXCEPTION_INT_DIVIDE_BY_ZERO:
+						// This code handles a division-by-zero exception
+						break;
+					default:
+						// We don't handle any other exceptions;
+						throw;
+					}
+				}
+			}
+											
+******************************************************************************/
+
+#pragma once
+
+#include <eh.h>
+
+#define MapSEx2CppEx()	CSE::MapSE2CE()
+
+class CSE
+{
+public:
+	// 结构化异常转换成 C++ 异常.
+	static void MapSE2CE() {_set_se_translator(TranslateSE2CE);}
+
+	operator DWORD() {return m_er.ExceptionCode;}
+
+	CSE(PEXCEPTION_POINTERS pep)
+		: m_er(*pep->ExceptionRecord)
+		, m_context(*pep->ContextRecord)
+	{
+	}
+
+	static void _cdecl TranslateSE2CE(UINT ec, PEXCEPTION_POINTERS pep) {throw CSE(pep);}
+
+private:
+	EXCEPTION_RECORD	m_er;			// CPU independent exception informaiton
+	CONTEXT				m_context;		// CPU dependent exception informaiton
+};

+ 6 - 1
source/hook/hp-src/STLHelper.h

@@ -21,7 +21,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
+#ifndef __STL_HELPER__
+#define __STL_HELPER__
+
 #pragma once
 
 #include "GeneralHelper.h"
@@ -1124,3 +1127,5 @@ private:
 	template<class _Other> smart_gd_array_ptr<_Ty>				(const smart_gd_array_ptr<_Other>&);
 	template<class _Other> smart_gd_array_ptr<_Ty>&	operator =	(const smart_gd_array_ptr<_Other>&);
 };
+
+#endif

+ 72 - 0
source/hook/hp-src/SysHelper.cpp

@@ -0,0 +1,72 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "stdafx.h"
+#include "SysHelper.h"
+#include "GeneralHelper.h"
+
+VOID SysGetSystemInfo(LPSYSTEM_INFO pInfo)
+{
+	ASSERT(pInfo != nullptr);
+	::GetNativeSystemInfo(pInfo);
+}
+
+DWORD SysGetNumberOfProcessors()
+{
+	SYSTEM_INFO si;
+	SysGetSystemInfo(&si);
+	
+	return si.dwNumberOfProcessors;
+}
+
+DWORD SysGetPageSize()
+{
+	SYSTEM_INFO si;
+	SysGetSystemInfo(&si);
+
+	return si.dwPageSize;
+}
+
+#if _MSC_VER < 1800
+
+BOOL SysGetOSVersionInfo(LPOSVERSIONINFO pInfo, BOOL bInfoEx)
+{
+	ASSERT(pInfo != nullptr);
+
+	pInfo->dwOSVersionInfoSize = bInfoEx ? sizeof(LPOSVERSIONINFOEX) : sizeof(LPOSVERSIONINFO);
+	return ::GetVersionEx(pInfo);
+}
+
+DWORD SysGetOSVersion()
+{
+	OSVERSIONINFO vi;
+	DWORD dwOSVersion = 0;
+
+	if(SysGetOSVersionInfo(&vi))
+		dwOSVersion = (vi.dwMajorVersion << 16) + vi.dwMinorVersion;
+
+	return dwOSVersion;
+}
+
+#endif

+ 41 - 0
source/hook/hp-src/SysHelper.h

@@ -0,0 +1,41 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// 获取系统信息
+VOID SysGetSystemInfo(LPSYSTEM_INFO pInfo);
+// 获取 CPU 核数
+DWORD SysGetNumberOfProcessors();
+// 获取页面大小
+DWORD SysGetPageSize();
+
+#if _MSC_VER < 1800
+
+// 获取操作系统版本
+BOOL SysGetOSVersionInfo(LPOSVERSIONINFO pInfo, BOOL bInfoEx = FALSE);
+// 获取操作系统版本(高位双字节:主版本号;低位双字节:副版本号)
+DWORD SysGetOSVersion();
+
+#endif

+ 26 - 0
source/hook/hp-src/Thread.cpp

@@ -0,0 +1,26 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+#include "Thread.h"

+ 329 - 0
source/hook/hp-src/Thread.h

@@ -0,0 +1,329 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <process.h>
+#include "RWLock.h"
+#include "STLHelper.h"
+
+template<class T> class CThread
+{
+public:
+	BOOL Start(T* pRunner, int iPriority = THREAD_PRIORITY_NORMAL, UINT uiStackSize = 0, LPSECURITY_ATTRIBUTES lpThreadAttributes = nullptr)
+	{
+		BOOL isOK = TRUE;
+
+		if(!IsRunning())
+		{
+			Release();
+
+			if(iPriority == THREAD_PRIORITY_NORMAL)
+				m_hThread = (HANDLE)_beginthreadex(lpThreadAttributes, uiStackSize, ThreadProc, (LPVOID)pRunner, 0, &m_uiThreadID);
+			else
+			{
+				m_hThread = (HANDLE)_beginthreadex(lpThreadAttributes, uiStackSize, ThreadProc, (LPVOID)pRunner, CREATE_SUSPENDED, &m_uiThreadID);
+
+				if(IsValid())
+				{
+					::SetThreadPriority(m_hThread, iPriority);
+					::ResumeThread(m_hThread);
+				}
+			}
+
+			if(IsValid())
+				m_pRunner = pRunner;
+			else
+			{
+				::SetLastError(_doserrno);
+				isOK = FALSE;
+			}
+		}
+		else
+		{
+			::SetLastError(ERROR_INVALID_STATE);
+			isOK = FALSE;
+		}
+
+		return isOK;
+	}
+
+	BOOL Join(BOOL bWithMessageLoop = FALSE, DWORD dwMilliseconds = INFINITE)
+	{
+		BOOL isOK = bWithMessageLoop											?
+			::MsgWaitForSingleObject(m_hThread, dwMilliseconds)					:
+			::WaitForSingleObject(m_hThread, dwMilliseconds) == WAIT_OBJECT_0	;
+
+		Release();
+
+		return isOK;
+	}
+
+	BOOL IsRunning()
+	{
+		if(!IsValid())
+			return FALSE;
+
+		DWORD dwExitCode;
+
+		if(GetExitCode(&dwExitCode))
+			return dwExitCode == STILL_ACTIVE;
+
+		return FALSE;
+	}
+
+	VOID Release()
+	{
+		if(IsValid())
+		{
+			::CloseHandle(m_hThread);
+			Reset();
+		}
+	}
+
+	HANDLE Detatch()
+	{
+		HANDLE h = m_hThread;
+
+		Reset();
+
+		return h;
+	}
+
+	BOOL Terminate		(DWORD dwExitCode)		{return ::TerminateThread(m_hThread, dwExitCode);}
+	BOOL GetExitCode	(LPDWORD lpExitCode)	{return ::GetExitCodeThread(m_hThread, lpExitCode);}
+	DWORD Suspend		()						{return ::SuspendThread(m_hThread);}
+	DWORD Resume		()						{return ::ResumeThread(m_hThread);}
+
+	BOOL IsValid		()	{return m_hThread != nullptr;}
+	T* GetRunner		()	{return m_pRunner;}
+	DWORD GetThreadID	()	{return m_uiThreadID;}
+
+	HANDLE& GetThreadHandle			() 			{return m_hThread;}
+	const HANDLE& GetThreadHandle	() const	{return m_hThread;}
+
+public:
+	CThread()
+	{
+		Reset();
+	}
+	
+	virtual ~CThread()
+	{
+		Release();
+	}
+
+private:
+	static UINT WINAPI ThreadProc(LPVOID pv)
+	{
+		return ((T*)pv)->Run();
+	}
+
+	void Reset()
+	{
+		m_uiThreadID = 0;
+		m_hThread	 = nullptr;
+		m_pRunner	 = nullptr;
+	}
+
+private:
+	UINT	m_uiThreadID;
+	HANDLE	m_hThread;
+	T*		m_pRunner;
+
+	DECLARE_NO_COPY_CLASS(CThread)
+};
+
+template<class T, typename construct_param_type = void*> class CTlsObj
+{
+	typedef unordered_map<DWORD, T*>			TLocalMap;
+	typedef typename TLocalMap::iterator		TLocalMapI;
+	typedef typename TLocalMap::const_iterator	TLocalMapCI;
+
+public:
+	T* TryGet(DWORD dwTID = 0)
+	{
+		T* pValue = nullptr;
+		if(dwTID == 0) dwTID = ::GetCurrentThreadId();
+
+		{
+			CReadLock locallock(m_lock);
+			TLocalMapCI it = m_map.find(dwTID);
+
+			if(it != m_map.end())
+				pValue = it->second;
+		}
+
+		return pValue;
+	}
+
+	T* Get()
+	{
+		DWORD dwTID	= ::GetCurrentThreadId();
+		T* pValue	= TryGet(dwTID);
+
+		if(pValue == nullptr)
+		{
+			CWriteLock locallock(m_lock);
+			TLocalMapCI it = m_map.find(dwTID);
+
+			if(it != m_map.end())
+				pValue = it->second;
+
+			if(pValue == nullptr)
+			{
+				pValue		 = Construct();
+				m_map[dwTID] = pValue;
+			}
+		}
+
+		return pValue;
+	}
+
+	T& GetRef()
+	{
+		return *Get();
+	}
+
+	T* Get(construct_param_type construct_param)
+	{
+		DWORD dwTID	= ::GetCurrentThreadId();
+		T* pValue	= TryGet(dwTID);
+
+		if(pValue == nullptr)
+		{
+
+			CWriteLock locallock(m_lock);
+			TLocalMapCI it = m_map.find(dwTID);
+
+			if(it != m_map.end())
+				pValue = it->second;
+
+			if(pValue == nullptr)
+			{
+				pValue		 = ConstructWithParam(construct_param);
+				m_map[dwTID] = pValue;
+			}
+		}
+
+		return pValue;
+	}
+
+	T& GetRef(construct_param_type construct_param)
+	{
+		return *Get(construct_param);
+	}
+
+	T* SetAndRetriveOldValue(T* pValue)
+	{
+		DWORD dwTID  = ::GetCurrentThreadId();
+		T* pOldValue = TryGet(dwTID);
+
+		if(pValue != pOldValue)
+		{
+			CWriteLock locallock(m_lock);
+			m_map[dwTID] = pValue;
+		}
+
+		return pOldValue;
+	}
+
+	void Set(T* pValue)
+	{
+		T* pOldValue = SetAndRetriveOldValue(pValue);
+
+		if(pValue != pOldValue)
+			Delete(pOldValue);
+	}
+
+	void Remove()
+	{
+		DWORD dwTID  = ::GetCurrentThreadId();
+		T* pOldValue = TryGet(dwTID);
+
+		Delete(pOldValue);
+
+		{
+			CWriteLock locallock(m_lock);
+			m_map.erase(dwTID);
+		}
+	}
+
+	void Clear()
+	{
+		CWriteLock locallock(m_lock);
+
+		if(!IsEmpty())
+		{
+			for(TLocalMapCI it = m_map.begin(); it != m_map.end(); ++it)
+				Delete(it->second);
+
+			m_map.clear();
+		}
+	}
+
+	TLocalMap&			GetLocalMap()			{return m_map;}
+	const TLocalMap&	GetLocalMap()	const	{return m_map;}
+
+	T*					operator ->	()			{return Get();}
+	const T*			operator ->	()	const	{return Get();}
+	T&					operator *	()			{return GetRef();}
+	const T&			operator *	()	const	{return GetRef();}
+	size_t Size			()				const	{return m_map.size();}
+	bool IsEmpty		()				const	{return m_map.empty();}
+
+public:
+	CTlsObj()
+	{
+
+	}
+
+	~CTlsObj()
+	{
+		Clear();
+	}
+
+private:
+	static inline void Delete(T* pValue)
+	{
+		if(pValue != nullptr)
+			delete pValue;
+	}
+
+	static inline T* Construct()
+	{
+		return new T;
+	}
+
+	static inline T* ConstructWithParam(construct_param_type construct_param)
+	{
+		return new T(construct_param);
+	}
+
+private:
+	CSimpleRWLock	m_lock;
+	TLocalMap		m_map;
+
+	DECLARE_NO_COPY_CLASS(CTlsObj)
+};

+ 150 - 0
source/hook/hp-src/WaitFor.cpp

@@ -0,0 +1,150 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "stdafx.h"
+#include "WaitFor.h"
+#include "GeneralHelper.h"
+#include "CriticalSection.h"
+
+#include <MmSystem.h>
+#pragma comment(lib, "Winmm")
+
+DWORD TimeGetTime()
+{
+	return ::timeGetTime();
+}
+
+DWORD GetTimeGap32(DWORD dwOriginal)
+{
+	return ::timeGetTime() - dwOriginal;
+}
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WS08
+ULONGLONG GetTimeGap64(ULONGLONG ullOriginal)
+{
+	return ::GetTickCount64() - ullOriginal;
+}
+#endif
+
+BOOL PeekMessageLoop(BOOL bDispatchQuitMsg)
+{
+	BOOL value = TRUE;
+
+	MSG msg;
+	while(::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
+	{
+		if(msg.message == WM_QUIT && !bDispatchQuitMsg)
+		{
+			value = FALSE;
+			break;
+		}
+
+		::TranslateMessage(&msg);
+		::DispatchMessage(&msg);
+	}
+
+	return value;
+}
+
+DWORD WaitForMultipleObjectsWithMessageLoop(DWORD dwHandles, HANDLE szHandles[], DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags)
+{
+	DWORD dwResult		= WAIT_FAILED;
+	DWORD dwBeginTime	= (dwMilliseconds == INFINITE) ? INFINITE : ::timeGetTime();
+
+	while(TRUE)
+	{
+		int iWaitTime;
+		if(dwBeginTime != INFINITE)
+		{
+			iWaitTime	= dwMilliseconds - (GetTimeGap32(dwBeginTime));
+
+			if(iWaitTime <= 0)
+			{
+				dwResult = WAIT_TIMEOUT;
+				break;
+			}
+		}
+		else
+			iWaitTime	= INFINITE;
+
+		dwResult = ::MsgWaitForMultipleObjectsEx(dwHandles, szHandles, iWaitTime, dwWakeMask, dwFlags);
+		ASSERT(dwResult != WAIT_FAILED);
+
+		if(dwResult == (WAIT_OBJECT_0 + dwHandles))
+			PeekMessageLoop();
+		else
+			break;
+	}
+
+	return dwResult;
+
+}
+
+BOOL MsgWaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags)
+{
+	DWORD dwResult = WaitForMultipleObjectsWithMessageLoop(1, &hHandle, dwMilliseconds, dwWakeMask, dwFlags);
+
+	switch(dwResult)
+	{
+	case WAIT_OBJECT_0:
+		return TRUE;
+	case WAIT_FAILED:
+		ASSERT(FALSE);
+	case WAIT_TIMEOUT:
+		return FALSE;
+	default:
+		ASSERT(FALSE);
+	}
+
+	return FALSE;
+}
+
+void WaitWithMessageLoop(DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags)
+{
+	static CEvt evWait;
+
+	VERIFY(MsgWaitForSingleObject(evWait, dwMilliseconds, dwWakeMask, dwFlags) == FALSE);
+}
+
+void WaitForWorkingQueue(long* plWorkingItemCount, long lMaxWorkingItemCount, DWORD dwCheckInterval)
+{
+	while(*plWorkingItemCount > lMaxWorkingItemCount)
+		::Sleep(dwCheckInterval);
+}
+
+void WaitForComplete(long* plWorkingItemCount, DWORD dwCheckInterval)
+{
+	WaitForWorkingQueue(plWorkingItemCount, 0, dwCheckInterval);
+}
+
+void MsgWaitForWorkingQueue(long* plWorkingItemCount, long lMaxWorkingItemCount, DWORD dwCheckInterval)
+{
+	while(*plWorkingItemCount > lMaxWorkingItemCount)
+		WaitWithMessageLoop(dwCheckInterval);
+}
+
+void MsgWaitForComplete(long* plWorkingItemCount, DWORD dwCheckInterval)
+{
+	MsgWaitForWorkingQueue(plWorkingItemCount, 0, dwCheckInterval);
+}

+ 138 - 0
source/hook/hp-src/WaitFor.h

@@ -0,0 +1,138 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+/* timeGetTime() 包装方法 */
+DWORD TimeGetTime();
+
+/**********************************
+描述: 获取当前时间与原始时间的时间差
+参数: 
+		dwOriginal	: 原始时间(毫秒),通常用 timeGetTime() 或 GetTickCount() 获取
+
+返回值:	与当前 timeGetTime() 之间的时间差
+**********************************/
+DWORD GetTimeGap32(DWORD dwOriginal);
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WS08
+/**********************************
+描述: 获取当前时间与原始时间的时间差
+参数: 
+		ullOriginal	: 原始时间(毫秒),通常用 GetTickCount64() 获取
+
+返回值:	与当前 GetTickCount64() 之间的时间差
+**********************************/
+ULONGLONG GetTimeGap64(ULONGLONG ullOriginal);
+#endif
+
+/**********************************
+描述: 处理Windows消息
+参数: 
+			bDispatchQuitMsg	: 是否转发 WM_QUIT 消息
+									TRUE : 转发(默认)
+									FALSE: 不转发,并返回 FALSE
+
+返回值:		TRUE  : 收完消息
+			FALSE : bDispatchQuitMsg 参数为 FALSE 并收到 WM_QUIT 消息		
+**********************************/
+BOOL PeekMessageLoop(BOOL bDispatchQuitMsg = TRUE);
+
+/**********************************
+描述: 等待指定时间, 同时处理Windows消息
+参数: (参考: MsgWaitForMultipleObjectsEx() )
+		dwHandles		: 数组元素个数
+		szHandles		: 对象句柄数组
+		dwMilliseconds	: 等待时间 (毫秒)
+		dwWakeMask		: 消息过滤标识
+		dwFlags			: 等待类型
+
+返回值: (0 ~ dwHandles - 1): 等待成功
+		WAIT_TIMEOUT		: 超时
+		WAIT_FAILED			: 执行失败
+**********************************/
+DWORD WaitForMultipleObjectsWithMessageLoop(DWORD dwHandles, HANDLE szHandles[], DWORD dwMilliseconds = INFINITE, DWORD dwWakeMask = QS_ALLINPUT, DWORD dwFlags = MWMO_INPUTAVAILABLE);
+
+/**********************************
+描述: 等待指定时间, 同时处理Windows消息
+参数: (参考: MsgWaitForMultipleObjectsEx() )
+		hHandle			: 对象句柄
+		dwMilliseconds	: 等待时间 (毫秒)
+		dwWakeMask		: 消息过滤标识
+		dwFlags			: 等待类型
+
+返回值: TRUE: 等待成功,FALSE: 超时		
+**********************************/
+BOOL MsgWaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds = INFINITE, DWORD dwWakeMask = QS_ALLINPUT, DWORD dwFlags = MWMO_INPUTAVAILABLE);
+
+/**********************************
+描述: 等待指定时间, 同时处理Windows消息
+参数: (参考: MsgWaitForMultipleObjectsEx() )
+		dwMilliseconds	: 等待时间 (毫秒)
+		dwWakeMask		: 消息过滤标识
+		dwFlags			: 等待类型
+
+返回值: MsgWaitForMultipleObjectsEx() 函数的操作结果		
+**********************************/
+void WaitWithMessageLoop(DWORD dwMilliseconds, DWORD dwWakeMask = QS_ALLINPUT, DWORD dwFlags = MWMO_INPUTAVAILABLE);
+
+/**********************************
+描述: 等待用Sleep()函数等待某个变量小于指定值
+参数: 
+		plWorkingItemCount		: 监视变量
+		lMaxWorkingItemCount	: 指定值
+		dwCheckInterval			: 检查间隔 (毫秒)
+
+返回值: 		
+**********************************/
+void WaitForWorkingQueue(long* plWorkingItemCount, long lMaxWorkingItemCount, DWORD dwCheckInterval);
+/**********************************
+描述: 等待用Sleep()函数等待某个变量减小到 0
+参数: 
+		plWorkingItemCount		: 监视变量
+		dwCheckInterval			: 检查间隔 (毫秒)
+
+返回值: 		
+**********************************/
+void WaitForComplete	(long* plWorkingItemCount, DWORD dwCheckInterval);
+
+/**********************************
+描述: 等待用WaitWithMessageLoop()函数等待某个变量小于指定值
+参数: 
+		plWorkingItemCount		: 监视变量
+		lMaxWorkingItemCount	: 指定值
+		dwCheckInterval			: 检查间隔 (毫秒)
+
+返回值: 		
+**********************************/
+void MsgWaitForWorkingQueue	(long* plWorkingItemCount, long lMaxWorkingItemCount, DWORD dwCheckInterval = 10);
+/**********************************
+描述: 等待用WaitWithMessageLoop()函数等待某个变量减小到 0
+参数: 
+		plWorkingItemCount		: 监视变量
+		dwCheckInterval			: 检查间隔 (毫秒)
+
+返回值: 		
+**********************************/
+void MsgWaitForComplete		(long* plWorkingItemCount, DWORD dwCheckInterval = 10);

+ 13 - 22
source/hook/hp-src/helper.cpp

@@ -366,48 +366,41 @@ void PostOnMessageBegin(CONNID dwConnID, LPCTSTR lpszName)
 	PostInfoMsg(msg);
 }
 
-void PostOnRequestLine(CONNID dwConnID, LPCSTR lpszMethod, USHORT usUrlFieldSet, LPCSTR lpszUrl, LPCTSTR lpszName)
+void PostOnRequestLine(CONNID dwConnID, LPCTSTR lpszMethod, USHORT usUrlFieldSet, LPCTSTR lpszUrl, LPCTSTR lpszName)
 {
-	USES_CONVERSION;
-
-	int content_len		= (int)(strlen(lpszMethod) + strlen(lpszUrl) + 20);
+	int content_len		= (int)(_tclen(lpszMethod) + _tclen(lpszUrl) + 20);
 	LPTSTR lpszContent	= new TCHAR[content_len];
 
-	wsprintf(lpszContent, _T("[%s/0x%02X] : %s"), A2T(lpszMethod), usUrlFieldSet, A2T(lpszUrl));
+	wsprintf(lpszContent, _T("[%s/0x%02X] : %s"), lpszMethod, usUrlFieldSet, lpszUrl);
 	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_REQUEST_LINE, content_len, lpszContent, lpszName);
 
 	PostInfoMsg(msg);
 }
 
-void PostOnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc, LPCTSTR lpszName)
+void PostOnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCTSTR lpszDesc, LPCTSTR lpszName)
 {
-	USES_CONVERSION;
-
-	int content_len		= (int)(strlen(lpszDesc) + 10);
+	int content_len		= (int)(_tclen(lpszDesc) + 10);
 	LPTSTR lpszContent	= new TCHAR[content_len];
 
-	wsprintf(lpszContent, _T("(%u) : %s"), usStatusCode, A2T(lpszDesc));
+	wsprintf(lpszContent, _T("(%u) : %s"), usStatusCode, lpszDesc);
 	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_STATUS_LINE, content_len, lpszContent, lpszName);
 
 	PostInfoMsg(msg);
 }
 
-void PostOnHeader(CONNID dwConnID, LPCSTR lpszHeaderName, LPCSTR lpszHeaderValue, LPCTSTR lpszName)
+void PostOnHeader(CONNID dwConnID, LPCTSTR lpszHeaderName, LPCTSTR lpszHeaderValue, LPCTSTR lpszName)
 {
-	USES_CONVERSION;
-
-	int content_len		= (int)(strlen(lpszHeaderName) + strlen(lpszHeaderValue) + 10);
+	int content_len = (int)(_tclen(lpszHeaderName) + _tclen(lpszHeaderValue)+10);
 	LPTSTR lpszContent	= new TCHAR[content_len];
 
-	wsprintf(lpszContent, _T("%s: %s"), A2T(lpszHeaderName), A2T(lpszHeaderValue));
+	wsprintf(lpszContent, _T("%s: %s"), lpszHeaderName, lpszHeaderValue);
 	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_HEADER, content_len, lpszContent, lpszName);
 
 	PostInfoMsg(msg);
 }
 
-void PostOnHeadersComplete(CONNID dwConnID, LPCSTR lpszSummary, LPCTSTR lpszName)
+void PostOnHeadersComplete(CONNID dwConnID, LPCTSTR lpszSummary, LPCTSTR lpszName)
 {
-	USES_CONVERSION;
 
 	static LPCTSTR PREFIX = _T("* * * * * * * * * Summary * * * * * * * * *\r\n");
 	static int PREFIX_LEN = lstrlen(PREFIX);
@@ -470,14 +463,12 @@ void PostOnUpgrade(CONNID dwConnID, EnHttpUpgradeType enUpgradeType, LPCTSTR lps
 	PostInfoMsg(msg);
 }
 
-void PostOnParseError(CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc, LPCTSTR lpszName)
+void PostOnParseError(CONNID dwConnID, int iErrorCode, LPCTSTR lpszErrorDesc, LPCTSTR lpszName)
 {
-	USES_CONVERSION;
-
-	int content_len		= (int)(strlen(lpszErrorDesc) + 10);
+	int content_len		= (int)(_tclen(lpszErrorDesc) + 10);
 	LPTSTR lpszContent	= new TCHAR[content_len];
 
-	wsprintf(lpszContent, _T("(%i) : %s"), iErrorCode, A2T(lpszErrorDesc));
+	wsprintf(lpszContent, _T("(%i) : %s"), iErrorCode, lpszErrorDesc);
 	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_PARSE_ERROR, content_len, lpszContent, lpszName);
 
 	PostInfoMsg(msg);

+ 5 - 5
source/hook/hp-src/helper.h

@@ -326,16 +326,16 @@ void PostServerStatics(const LONGLONG& llTotalSent, const LONGLONG& llTotalRecei
 void PostTimeConsuming(DWORD dwTickCount, LPCTSTR lpszName = nullptr);
 
 void PostOnMessageBegin(CONNID dwConnID, LPCTSTR lpszName = nullptr);
-void PostOnRequestLine(CONNID dwConnID, LPCSTR lpszMethod, USHORT usUrlFieldSet, LPCSTR lpszUrl, LPCTSTR lpszName = nullptr);
-void PostOnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc, LPCTSTR lpszName = nullptr);
-void PostOnHeader(CONNID dwConnID, LPCSTR lpszHeaderName, LPCSTR lpszHeaderValue, LPCTSTR lpszName = nullptr);
-void PostOnHeadersComplete(CONNID dwConnID, LPCSTR lpszSummary, LPCTSTR lpszName = nullptr);
+void PostOnRequestLine(CONNID dwConnID, LPCTSTR lpszMethod, USHORT usUrlFieldSet, LPCTSTR lpszUrl, LPCTSTR lpszName = nullptr);
+void PostOnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCTSTR lpszDesc, LPCTSTR lpszName = nullptr);
+void PostOnHeader(CONNID dwConnID, LPCTSTR lpszHeaderName, LPCTSTR lpszHeaderValue, LPCTSTR lpszName = nullptr);
+void PostOnHeadersComplete(CONNID dwConnID, LPCTSTR lpszSummary, LPCTSTR lpszName = nullptr);
 void PostOnBody(CONNID dwConnID, const BYTE* pData, int iLength, LPCTSTR lpszName = nullptr);
 void PostOnChunkHeader(CONNID dwConnID, int iLength, LPCTSTR lpszName = nullptr);
 void PostOnChunkComplete(CONNID dwConnID, LPCTSTR lpszName = nullptr);
 void PostOnMessageComplete(CONNID dwConnID, LPCTSTR lpszName = nullptr);
 void PostOnUpgrade(CONNID dwConnID, EnHttpUpgradeType enUpgradeType, LPCTSTR lpszName = nullptr);
-void PostOnParseError(CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc, LPCTSTR lpszName = nullptr);
+void PostOnParseError(CONNID dwConnID, int iErrorCode, LPCTSTR lpszErrorDesc, LPCTSTR lpszName = nullptr);
 
 void PostInfoMsg(info_msg* msg);
 void LogInfoMsg(info_msg* pInfoMsg);