#pragma once #define _CRT_SECURE_NO_DEPRECATE 1 #ifdef _WIN64 #define _WIN32_WINNT _WIN32_WINNT_WIN10 #define WINVER _WIN32_WINNT_VISTA #else #define _WIN32_WINNT _WIN32_WINNT_WIN10 #define WINVER _WIN32_WINNT_WIN10 #endif #define NTDDI_VERSION NTDDI_WIN10_RS3 #define WIN32_LEAN_AND_MEAN 1 #define UNICODE 1 #define _UNICODE 1 #define NOMINMAX #include #include //#include #include //#include #include #include #include "array.h" #include #include "ownedcs.h" #include "undocAPI.h" #include #include #include #include #include #include #include #include #include #include //#include //#include #define for if(0);else for #include #include #define STRSAFE_NO_DEPRECATE #include #define _CRTDBG_MAP_ALLOC #include #include #include #include #include using namespace std; #ifdef _M_IX86 //#include "optimize/optimize.h" #endif #define FONT_MAGIC_NUMBER 0xA8 #define ASSERT _ASSERTE #define Assert _ASSERTE #ifdef _DEBUG #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif #ifndef NOP_FUNCTION #if (_MSC_VER >= 1210) #define NOP_FUNCTION __noop #else #define NOP_FUNCTION (void)0 #endif //_MSC_VER #endif //!NOP_FUNCTION #ifndef C_ASSERT #define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] #endif //!C_ASSERT #ifndef FORCEINLINE #if (_MSC_VER >= 1200) #define FORCEINLINE __forceinline #else #define FORCEINLINE __inline #endif //_MSC_VER #endif //!FORCEINLINE void Log(char* Msg); void Log(wchar_t* Msg); // convert string to wstring inline std::wstring to_wide_string(const std::string & input) { std::wstring_convert> converter; return converter.from_bytes(input); } // convert wstring to string inline std::string to_byte_string(const std::wstring & input) { //std::wstring_convert> converter; std::wstring_convert> converter; return converter.to_bytes(input); } FORCEINLINE HINSTANCE GetDLLInstance() { extern HINSTANCE g_hinstDLL; return g_hinstDLL; } //排他制御 class CCriticalSectionLock { #define MAX_CRITICAL_COUNT 20 private: static CRITICAL_SECTION m_cs[MAX_CRITICAL_COUNT]; friend class CCriticalSectionLockTry; int m_index; public: enum { CS_LIBRARY, CS_CACHEDFONT, CS_FONTENG, //CS_CMAPCACHE, //CS_IMAGECACHE, CS_SETTING, CS_MAIN, CS_FONTCACHE, CS_MANAGER, CS_CREATEFONT, CS_FONTLINK, CS_FONTMAP, CS_OWNEDCS, CS_VIRTMEM, CS_DWRITE, }; CCriticalSectionLock(int index=CS_LIBRARY): m_index(index) { ::EnterCriticalSection(&m_cs[index]); } ~CCriticalSectionLock() { ::LeaveCriticalSection(&m_cs[m_index]); } static void Init() { for (int i=0;i //va_list #include //_vsnwprintf static void _Trace(LPCTSTR pszFormat, ...) { CCriticalSectionLock __lock; va_list argptr; va_start(argptr, pszFormat); //w(v)sprintfは1024文字以上返してこない TCHAR szBuffer[10240]; wvsprintf(szBuffer, pszFormat, argptr); //デバッガをアタッチしてる時はデバッガにメッセージを出す //if (IsDebuggerPresent()) { OutputDebugString(szBuffer); return; //} extern HANDLE g_hfDbgText; HANDLE hf = g_hfDbgText; if (!hf) { TCHAR szFileName[MAX_PATH+16]; GetModuleFileName(GetDLLInstance(), szFileName, MAX_PATH); TCHAR *p1 = _tcsrchr(szFileName, _T('\\')); if (p1 && p1 > szFileName) { *p1 = 0; TCHAR *p2 = _tcsrchr(szFileName, _T('\\')); if (p2) memmove(p2 + 1, p1 + 1, (_tcslen(p1) + 1) * sizeof(TCHAR)); } _tcscpy(szFileName + _tcslen(szFileName) - 4, L"_dbg.txt"); g_hfDbgText = hf = CreateFile(szFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if(hf != INVALID_HANDLE_VALUE) { SetFilePointer(hf, 0, NULL, FILE_BEGIN); #ifdef _UNICODE WORD w = 0xfeff; DWORD cb; WriteFile(hf, &w, sizeof(WORD), &cb, NULL); #endif } } if(hf != INVALID_HANDLE_VALUE) { DWORD cb; WriteFile(hf, szBuffer, _tcslen(szBuffer) * sizeof(TCHAR), &cb, NULL); } } #else //!_DEBUG #define TRACE NOP_FUNCTION //↓PSDK 2003R2のwinnt.h //#ifndef NOP_FUNCTION //#if (_MSC_VER >= 1210) //#define NOP_FUNCTION __noop //#else //#define NOP_FUNCTION (void)0 //#endif //#endif #endif //_DEBUG //TRACEマクロ //使用例: TRACE(_T("cx: %d\n"), cx); #ifdef USE_TRACE #define TRACE2 _Trace2 #define TRACE2_STR _Trace2_Str #define TRACE2_BIN _Trace2_Bin #include //va_list #include //_vsnwprintf static void _Trace2(LPCTSTR pszFormat, ...) { CCriticalSectionLock __lock; va_list argptr; va_start(argptr, pszFormat); //w(v)sprintfは1024文字以上返してこない TCHAR szBuffer[1024]; wvsprintf(szBuffer, pszFormat, argptr); OutputDebugString(szBuffer); } static void _Trace2_Bin(LPWSTR func, int line, LPVOID lpString, UINT cbString) { const PBYTE srcp = (const PBYTE)lpString; WCHAR buf[0x1000]; LPWSTR p = buf; for (UINT i = 0; i < 32 && i < cbString; ++i) { wsprintf(p, L"%02x ", srcp[i]); p += lstrlen(p); } *p = 0; TRACE(_T("%s %d: %d %08x %s\n"), func, line, cbString, lpString, buf); } static void _Trace2_Str(LPWSTR func, int line, LPCWSTR lpString, UINT cbString) { WCHAR buf[0x1000]; UINT len = Min(cbString, countof(buf) - 1); lstrcpyn(buf, lpString, len + 1); buf[countof(buf) - 1] = 0; TRACE(_T("%s %d: %d %s\n"), func, line, cbString, buf); LPWSTR p = buf; for (UINT i = 0; i < 32 && i < cbString; ++i) { wsprintf(p, L"%04x ", lpString[i]); p += lstrlen(p); } TRACE(_T("%s %d: %d %08x %s\n"), func, line, cbString, lpString, buf); } #else //!USE_TRACE #define TRACE2 NOP_FUNCTION #define TRACE2_STR NOP_FUNCTION #define TRACE2_BIN NOP_FUNCTION #endif //USE_TRACE class COwnedCriticalSectionLock { private: static OWNED_CRITIAL_SECTION m_cs[2]; WORD FOwner; int m_index; public: enum { OCS_FREETYPE, OCS_DC }; COwnedCriticalSectionLock():FOwner(0), m_index(OCS_FREETYPE) { EnterOwnedCritialSection(&m_cs[m_index], FOwner); } COwnedCriticalSectionLock(WORD Owner, int index=OCS_FREETYPE):FOwner(Owner), m_index(index) { EnterOwnedCritialSection(&m_cs[m_index], Owner); } ~COwnedCriticalSectionLock() { LeaveOwnedCritialSection(&m_cs[m_index], FOwner); } static void Init() { for (int i=0;i<2;i++) { InitializeOwnedCritialSection(&m_cs[i]); } } static void Term() { for (int i=0;i<2;i++) { DeleteOwnedCritialSection(&m_cs[i]); } } }; class CThreadCounter { private: static LONG interlock; public: CThreadCounter() { InterlockedIncrement(&interlock); } ~CThreadCounter() { InterlockedDecrement(&interlock); } static void Init() { interlock = 0; } static int Count() { return InterlockedExchange(&interlock, interlock); } }; class CCriticalSectionLockTry { public: BOOL TryEnter(int index=CCriticalSectionLock::CS_LIBRARY) { return ::TryEnterCriticalSection(&CCriticalSectionLock::m_cs[index]); } int CritalCount(int index=CCriticalSectionLock::CS_LIBRARY) { return CCriticalSectionLock::m_cs[index].RecursionCount; } void Leave(int index=CCriticalSectionLock::CS_LIBRARY) { ::LeaveCriticalSection(&CCriticalSectionLock::m_cs[index]); } }; // 使用後はfreeで開放する事 LPWSTR _StrDupExAtoW(LPCSTR pszMB, int cchMB, LPWSTR pszStack, int cchStack, int* pcchWC, int nACP = CP_ACP); static inline LPWSTR _StrDupAtoW(LPCSTR pszMB, int cchMB = -1, int* pcchWC = NULL) { return _StrDupExAtoW(pszMB, cchMB, NULL, 0, pcchWC); } // useful macros #define NOCOPY(T) T(const T&); T& operator=(const T&) #define countof(array) (sizeof(array)/sizeof(array[0])) #define sizeof_struct(s, m) (((int)((char*)(&((s*)0)->m) - ((char*)((s*)0)))) + sizeof(((s*)0)->m)) #ifndef offsetof #define offsetof(s,m) (size_t)&(((s*)0)->m) #endif #ifdef _DEBUG #define Verify(expr) _ASSERTE(expr) #else #define Verify(expr) (expr) #endif template FORCEINLINE T Min(T x, T y) { return (x < y) ? x : y; } template FORCEINLINE T Max(T x, T y) { return (y < x) ? x : y; } template FORCEINLINE T Bound(T x, T m, T M) { return (x < m) ? m : ((x > M) ? M : x); } template FORCEINLINE int Sgn(T x, T y) { return (x > y) ? 1 : ((x < y) ? -1 : 0); } //型チェック機能つきDeleteXXX/SelectXXX //SelectObject/DeleteObjectは使用できなくなる #ifdef _DEBUG #undef DeletePen #undef DeleteBrush #undef DeleteRgn #undef DeleteFont #undef DeleteBitmap #undef SelectPen #undef SelectBrush #undef SelectRgn #undef SelectFont #undef SelectBitmap #define _IsValidPen(hPen) \ (hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN || ::GetObjectType(hPen) == OBJ_EXTPEN) #define _IsValidBrush(hBrush) \ (hBrush == NULL || ::GetObjectType(hBrush) == OBJ_BRUSH) #define _IsValidRgn(hRgn) \ (hRgn == NULL || ::GetObjectType(hRgn) == OBJ_REGION) #define _IsValidFont(hFont) \ (hFont == NULL || ::GetObjectType(hFont) == OBJ_FONT) #define _IsValidBitmap(hBitmap) \ (hBitmap == NULL || ::GetObjectType(hBitmap) == OBJ_BITMAP) #define DEFINE_DELETE_FUNCTION(type, name) \ FORCEINLINE BOOL WINAPI Delete##name(type h##name) \ { \ _ASSERTE(_IsValid##name(h##name)); \ return ::DeleteObject(h##name); \ } #define DEFINE_SELECT_FUNCTION(type, name) \ FORCEINLINE type WINAPI Select##name(HDC hDC, type h##name) \ { \ _ASSERTE(hDC != NULL); \ if (!_IsValid##name(h##name)) { \ TRACE(_T("Select object %x for DC %x"), (DWORD)h##name, (DWORD)hDC); \ }; \ return (type)::SelectObject(hDC, h##name); \ } DEFINE_DELETE_FUNCTION(HPEN, Pen) DEFINE_DELETE_FUNCTION(HBRUSH, Brush) DEFINE_DELETE_FUNCTION(HRGN, Rgn) DEFINE_DELETE_FUNCTION(HFONT, Font) DEFINE_DELETE_FUNCTION(HBITMAP, Bitmap) DEFINE_SELECT_FUNCTION(HPEN, Pen) DEFINE_SELECT_FUNCTION(HBRUSH, Brush) DEFINE_SELECT_FUNCTION(HRGN, Rgn) DEFINE_SELECT_FUNCTION(HFONT, Font) DEFINE_SELECT_FUNCTION(HBITMAP, Bitmap) #undef _IsValidPen #undef _IsValidBrush #undef _IsValidRgn #undef _IsValidFont #undef _IsValidBitmap #undef DEFINE_DELETE_FUNCTION #undef DEFINE_SELECT_FUNCTION #if (_MSC_VER >= 1300) #pragma deprecated(DeleteObject) #pragma deprecated(SelectObject) #else //_MSC_VER < 1300 #undef DeleteObject #define DeleteObject DeleteObject_instead_use_DeleteXXX #undef SelectObject #define SelectObject SelectObject_instead_use_DeleteXXX #endif //_MSC_VER #else //!_DEBUG #ifndef _INC_WINDOWSX #define DeletePen ::DeleteObject #define DeleteBrush ::DeleteObject #define DeleteRgn ::DeleteObject #define DeleteFont ::DeleteObject #define DeleteBitmap ::DeleteObject #define SelectPen(d,o) (HPEN)::SelectObject(d,o) #define SelectBrush(d,o) (HBRUSH)::SelectObject(d,o) #define SelectRgn(d,o) (HRGN)::SelectObject(d,o) #define SelectFont(d,o) (HFONT)::SelectObject(d,o) #define SelectBitmap(d,o) (HBITMAP)::SelectObject(d,o) #endif //!_INC_WINDOWSX #endif //_DEBUG //TRACEマクロ //使用例: TRACE(_T("cx: %d\n"), cx); #ifndef _WIN64 #ifdef _DEBUG FORCEINLINE static __int64 GetClockCount() { LARGE_INTEGER cycles; __asm { rdtsc mov cycles.LowPart, eax mov cycles.HighPart, edx } return cycles.QuadPart; } //使用例 //{ // CDebugElapsedCounter _cntr("hogehoge"); // : (適当な処理) //} //出力例: "hogehoge: 10000 clocks" class CDebugElapsedCounter { private: __int64 m_ilClk; LPCSTR m_pszName; public: CDebugElapsedCounter(LPCSTR psz) : m_ilClk(GetClockCount()) , m_pszName(psz) { } ~CDebugElapsedCounter() { TRACE(_T("%hs: %u clocks\n"), m_pszName, (DWORD)(GetClockCount() - m_ilClk)); } }; #else class CDebugElapsedCounter { public: CDebugElapsedCounter(LPCSTR psz) { } }; #endif #endif //String to int等系列函数的定义 /* int _StrToInt(LPCTSTR pStr, int nDefault) { #define isspace(ch) (ch == _T('\t') || ch == _T(' ')) #define isdigit(ch) ((_TUCHAR)(ch - _T('0')) <= 9) int ret; bool neg = false; LPCTSTR pStart; for (; isspace(*pStr); pStr++); switch (*pStr) { case _T('-'): neg = true; case _T('+'): pStr++; break; } pStart = pStr; ret = 0; for (; isdigit(*pStr); pStr++) { ret = 10 * ret + (*pStr - _T('0')); } if (pStr == pStart) { return nDefault; } return neg ? -ret : ret; #undef isspace #undef isdigit } int _httoi(const TCHAR *value) { struct CHexMap { TCHAR chr; int value; }; const int HexMapL = 16; CHexMap HexMap[HexMapL] = { {'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'A', 10}, {'B', 11}, {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15} }; TCHAR *mstr = _tcsupr(_tcsdup(value)); TCHAR *s = mstr; int result = 0; if (*s == '0' && *(s + 1) == 'X') s += 2; bool firsttime = true; while (*s != '\0') { bool found = false; for (int i = 0; i < HexMapL; i++) { if (*s == HexMap[i].chr) { if (!firsttime) result <<= 4; result |= HexMap[i].value; found = true; break; } } if (!found) break; s++; firsttime = false; } free(mstr); return result; } //atofにデフォルト値を返せるようにしたような物 float _StrToFloat(LPCTSTR pStr, float fDefault) { #define isspace(ch) (ch == _T('\t') || ch == _T(' ')) #define isdigit(ch) ((_TUCHAR)(ch - _T('0')) <= 9) int ret_i; int ret_d; float ret; bool neg = false; LPCTSTR pStart; for (; isspace(*pStr); pStr++); switch (*pStr) { case _T('-'): neg = true; case _T('+'): pStr++; break; } pStart = pStr; ret = 0; ret_i = 0; ret_d = 1; for (; isdigit(*pStr); pStr++) { ret_i = 10 * ret_i + (*pStr - _T('0')); } if (*pStr == _T('.')) { pStr++; for (; isdigit(*pStr); pStr++) { ret_i = 10 * ret_i + (*pStr - _T('0')); ret_d *= 10; } } ret = (float)ret_i / (float)ret_d; if (pStr == pStart) { return fDefault; } return neg ? -ret : ret; #undef isspace #undef isdigit }*/ void HookD2DDll(); bool HookD2D1(); void HookGdiplus(); void ChangeFileName(LPWSTR lpSrc, int nSize, LPCWSTR lpNewFileName); std::wstring MakeUniqueFontName(const std::wstring strFullName, const std::wstring strFamilyName, const std::wstring strStyleName); std::string WstringToString(const std::wstring str);