// XTPSkinManagerApiHook.cpp: implementation of the CXTPSkinManagerApiHook class. // // This file is a part of the XTREME SKINFRAMEWORK MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include #pragma comment(lib, "imagehlp.lib") #include "Common/XTPVC80Helpers.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPWinThemeWrapper.h" #include "XTPSkinManager.h" #include "XTPSkinManagerSchema.h" #include "XTPSkinObject.h" #include "XTPSkinObjectFrame.h" #include "XTPSkinObjectMenu.h" #include "XTPSkinDrawTools.h" #include "XTPSkinManagerApiHook.h" #include "XTPSkinManagerModuleList.h" #include "XTPSkinManagerResource.h" #ifdef _UNICODE #define lpszSystemParametersInfo "SystemParametersInfoW" #else #define lpszSystemParametersInfo "SystemParametersInfoA" #endif int XTPCompareStringNoCase(const char* dst, const char* src) { int f, l; do { f = (unsigned char)(*(dst++)); if ((f >= 'A') && (f <= 'Z')) f -= ('A' - 'a'); l = (unsigned char)(*(src++)); if ((l >= 'A') && (l <= 'Z')) l -= ('A' - 'a'); } while ( f && (f == l) ); return (f - l); } int XTPCompareStringNoCase(const TCHAR* dst, const TCHAR* src, int len) { int f, l; do { f = (TCHAR)(*(dst++)); if ((f >= 'A') && (f <= 'Z')) f -= ('A' - 'a'); l = (TCHAR)(*(src++)); if ((l >= 'A') && (l <= 'Z')) l -= ('A' - 'a'); len--; } while ( f && (f == l) && len != 0); return (f - l); } CXTPSkinManagerApiHook::CXTPSkinManagerApiHook() { m_bInitialized = FALSE; ZeroMemory(&m_arrFunctions, sizeof(m_arrFunctions)); ExcludeModule(_T("SHLWAPI.DLL"), TRUE); ExcludeModule(_T("COMCTL32.DLL"), TRUE); ExcludeModule(_T("KERNEL32.DLL"), FALSE); ExcludeModule(_T("USER32.DLL"), FALSE); ExcludeModule(_T("GDI32.DLL"), FALSE); ExcludeModule(_T("WININET.DLL"), FALSE); ExcludeModule(_T("MSCTF.DLL"), FALSE); ::InitializeCriticalSection(&m_cs); } CXTPSkinManagerApiHook::~CXTPSkinManagerApiHook() { FinalizeHookManagement(); ::DeleteCriticalSection(&m_cs); } void CXTPSkinManagerApiHook::ConnectWrapper(CXTPWinThemeWrapper* pThemeWrapper) { pThemeWrapper->CreateSharedData(); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperOpenThemeData, &CXTPSkinManagerApiHook::OnHookOpenThemeData); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperDrawThemeBackground, &CXTPSkinManagerApiHook::OnHookDrawThemeBackground); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperCloseThemeData, &CXTPSkinManagerApiHook::OnHookCloseThemeData); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperGetThemeColor, &CXTPSkinManagerApiHook::OnHookGetThemeColor); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperGetThemeInt, &CXTPSkinManagerApiHook::OnHookGetThemeInt); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperIsAppThemed, &CXTPSkinManagerApiHook::OnHookIsAppThemed); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperIsThemeActive, &CXTPSkinManagerApiHook::OnHookIsThemeActive); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperGetCurrentThemeName, &CXTPSkinManagerApiHook::OnHookGetCurrentThemeName); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperGetThemeSysBool, &CXTPSkinManagerApiHook::OnHookGetThemeSysBool); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperGetThemeSysColor, &CXTPSkinManagerApiHook::OnHookGetThemeSysColor); pThemeWrapper->SetThemeWrapperPtr(xtpWrapperGetThemePartSize, &CXTPSkinManagerApiHook::OnHookGetThemePartSize); } CXTPSkinManagerApiHook* CXTPSkinManagerApiHook::GetInstance() { static CXTPSkinManagerApiHook instance; return &instance; } void CXTPSkinManagerApiHook::ExcludeModule(LPCTSTR lpszModule, BOOL bWin9x) { EXCLUDEDMODULE em; em.bWin9x = bWin9x; em.strModule = lpszModule; em.hModule = 0; m_arrExcludedModules.Add(em); } BOOL CXTPSkinManagerApiHook::IsModuleExcluded(HMODULE hModule) const { BOOL bWin9x = XTPSkinManager()->IsWin9x(); for (int i = 0; i < (int)m_arrExcludedModules.GetSize(); i++) { const EXCLUDEDMODULE& em = m_arrExcludedModules[i]; if (em.bWin9x && !bWin9x) continue; if (em.hModule == hModule) return TRUE; if (em.strModule[em.strModule.GetLength() - 1] == '*') { TCHAR fn[MAX_PATH]; GetModuleFileName(hModule, fn, MAX_PATH); TCHAR* lpszName =_tcsrchr(fn, '\\'); if (lpszName == NULL) lpszName = fn; else lpszName++; if (XTPCompareStringNoCase(lpszName, em.strModule, em.strModule.GetLength() - 1) == 0) return TRUE; } } return FALSE; } void CXTPSkinManagerApiHook::UnhookAllFunctions() { for (int i = 0; i < XTP_SKIN_APIHOOKCOUNT; i++) { CXTPSkinManagerApiFunction* pHook = m_arrFunctions[i]; if (pHook) { pHook->UnhookImport(); delete pHook; m_arrFunctions[i] = NULL; } } ZeroMemory(&m_arrFunctions, sizeof(m_arrFunctions)); } CXTPSkinManagerApiFunction* CXTPSkinManagerApiHook::HookImport(XTPSkinFrameworkApiFunctionIndex nIndex, LPCSTR pszCalleeModName, LPCSTR pszFuncName, PROC pfnHook) { CXTPSkinManagerApiFunction* pResult = NULL; try { if (!GetHookedFunction(pszCalleeModName, pszFuncName)) { if (XTPCompareStringNoCase(pszCalleeModName, "UXTHEME.DLL") == 0) { return AddHook(nIndex, pszCalleeModName, pszFuncName, NULL, pfnHook); } PROC pfnOrig = GetProcAddressWindows(::GetModuleHandleA(pszCalleeModName), pszFuncName); if (NULL == pfnOrig) { HMODULE hmod = ::LoadLibraryA(pszCalleeModName); if (hmod) { pfnOrig = GetProcAddressWindows(::GetModuleHandleA(pszCalleeModName), pszFuncName); } } if (pfnOrig) { pResult = AddHook(nIndex, pszCalleeModName, pszFuncName, pfnOrig,pfnHook); } } } catch(...) { } return pResult; } CXTPSkinManagerApiFunction* CXTPSkinManagerApiHook::AddHook(XTPSkinFrameworkApiFunctionIndex nIndex, LPCSTR pszCalleeModName, LPCSTR pszFuncName, PROC pfnOrig, PROC pfnHook) { ASSERT(!GetHookedFunction(pszCalleeModName, pszFuncName)); ASSERT(!GetHookedFunction(nIndex)); ASSERT(nIndex < XTP_SKIN_APIHOOKCOUNT); if (nIndex >= XTP_SKIN_APIHOOKCOUNT) return NULL; CXTPSkinManagerApiFunction* pHook = new CXTPSkinManagerApiFunction(this, pszCalleeModName, pszFuncName, pfnOrig, pfnHook); m_arrFunctions[nIndex] = pHook; pHook->HookImport(); return pHook; } FARPROC WINAPI CXTPSkinManagerApiHook::GetProcAddressWindows(HMODULE hModule, LPCSTR pszProcName) { typedef FARPROC (WINAPI* LPFNGETPROCADDRESS)(HMODULE hModule, LPCSTR pszProcName); PROC pfnOrig = GetOriginalProc(xtpSkinApiGetProcAddress); if (pfnOrig) return ((LPFNGETPROCADDRESS)pfnOrig)(hModule, pszProcName); return ::GetProcAddress(hModule, pszProcName); } LRESULT WINAPI CXTPSkinManagerApiHook::CallWindowProcOrig(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { typedef LRESULT (WINAPI* LPFNCALLWINDOWPROC)(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); #ifdef _UNICODE PROC pfnOrig = GetOriginalProc(xtpSkinApiCallWindowProcW); #else PROC pfnOrig = GetOriginalProc(xtpSkinApiCallWindowProcA); #endif if (pfnOrig) return ((LPFNCALLWINDOWPROC)pfnOrig)(lpPrevWndFunc, hWnd, Msg, wParam, lParam); return ::CallWindowProc(lpPrevWndFunc, hWnd, Msg, wParam, lParam); } CXTPSkinManagerApiFunction* CXTPSkinManagerApiHook::GetHookedFunction(XTPSkinFrameworkApiFunctionIndex nIndex) { ASSERT(nIndex < XTP_SKIN_APIHOOKCOUNT); if (nIndex < 0 || nIndex >= XTP_SKIN_APIHOOKCOUNT) return NULL; return m_arrFunctions[nIndex]; } PROC AFX_CDECL CXTPSkinManagerApiHook::GetOriginalProc(XTPSkinFrameworkApiFunctionIndex nIndex) { CXTPSkinManagerApiFunction* pFunction = GetInstance()->GetHookedFunction(nIndex); if (!pFunction) return NULL; return pFunction->m_pfnOrig; } CXTPSkinManagerApiFunction* CXTPSkinManagerApiHook::GetHookedFunction(LPCSTR pszCalleeModName, LPCSTR pszFuncName) { for (int i = 0; i < XTP_SKIN_APIHOOKCOUNT; i++) { CXTPSkinManagerApiFunction* pHook = m_arrFunctions[i]; if (!pHook) { continue; } if (XTPCompareStringNoCase(pHook->m_szCalleeModName, pszCalleeModName) == 0 && XTPCompareStringNoCase(pHook->m_szFuncName, pszFuncName) == 0) { return pHook; } } return NULL; } // // The PUSH opcode on x86 platforms // const BYTE cPushOpCode = 0x68; PVOID CXTPSkinManagerApiFunction::sm_pvMaxAppAddr = NULL; PVOID CXTPSkinManagerApiFunction::sm_pfnAfxWndProc = NULL; ////////////////////////////////////////////////////////////////////////// // CXTPSkinManagerApiFunction CXTPSkinManagerApiFunction::CXTPSkinManagerApiFunction( CXTPSkinManagerApiHook* pApiHook, LPCSTR pszCalleeModName, LPCSTR pszFuncName, PROC pfnOrig, PROC pfnHook) : m_pApiHook(pApiHook), m_bHooked(FALSE), m_pfnOrig(pfnOrig), m_pfnHook(pfnHook) { #if (_MSC_VER > 1310) // VS2005 strcpy_s(m_szCalleeModName, 50, pszCalleeModName); strcpy_s(m_szFuncName, 30, pszFuncName); #else strcpy(m_szCalleeModName, pszCalleeModName); strcpy(m_szFuncName, pszFuncName); #endif if (sm_pfnAfxWndProc == NULL) { sm_pfnAfxWndProc = (FARPROC)AfxGetAfxWndProc(); } if (sm_pvMaxAppAddr == NULL) { // // Functions with address above lpMaximumApplicationAddress require // special processing (Windows 9x only) // SYSTEM_INFO si; GetSystemInfo(&si); sm_pvMaxAppAddr = si.lpMaximumApplicationAddress; } if (m_pfnOrig > sm_pvMaxAppAddr) { // // The address is in a shared DLL; the address needs fixing up // PBYTE pb = (PBYTE) m_pfnOrig; if (pb[0] == cPushOpCode) { // // Skip over the PUSH op code and grab the real address // PVOID pv = * (PVOID*) &pb[1]; m_pfnOrig = (PROC) pv; } } } CXTPSkinManagerApiFunction::~CXTPSkinManagerApiFunction() { UnhookImport(); } BOOL CXTPSkinManagerApiFunction::HookImport() { return m_bHooked = ReplaceInAllModules(m_szCalleeModName, m_pfnOrig, m_pfnHook); } BOOL CXTPSkinManagerApiFunction::UnhookImport() { if (m_bHooked) { ReplaceInAllModules(m_szCalleeModName, m_pfnHook, m_pfnOrig); m_bHooked = FALSE; } return !m_bHooked; } BOOL CXTPSkinManagerApiFunction::ReplaceInAllModules(LPCSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew) { BOOL bResult = FALSE; if ((NULL != pfnCurrent) && (NULL != pfnNew)) { HINSTANCE hInstance = AfxGetInstanceHandle(); CXTPSkinManagerModuleList moduleList(::GetCurrentProcessId()); HMODULE hModule = moduleList.GetFirstModule(); while (hModule) { #ifdef _DEBUG TCHAR fn[MAX_PATH]; GetModuleFileName(hModule, fn, MAX_PATH); #endif if ((hModule != hInstance) && !m_pApiHook->IsModuleExcluded(hModule)) { if (ReplaceInOneModule(pszCalleeModName, pfnCurrent, pfnNew, hModule)) { bResult = TRUE; } } hModule = moduleList.GetNextModule(); } if (ReplaceInOneModule(pszCalleeModName, pfnCurrent, pfnNew, hInstance)) { bResult = TRUE; } } return bResult; } BOOL CXTPSkinManagerApiFunction::ReplaceInOneModule(LPCSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) { if (pfnCurrent == NULL || pfnNew == NULL) return FALSE; CXTPLockGuard lock(m_pApiHook->m_cs); try { ULONG ulSize; // Get the address of the module's import section PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData( hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize ); // Does this module has import section ? if (pImportDesc == NULL) return FALSE; while (pImportDesc != NULL) { // Loop through all descriptors and // find the import descriptor containing references to callee's functions while (pImportDesc->Name) { LPCSTR lpszName = ((LPCSTR)((PBYTE) hmodCaller + pImportDesc->Name)); if (XTPCompareStringNoCase(lpszName, pszCalleeModName) == 0) break; // Found pImportDesc++; } // while // Does this module import any functions from this callee ? if (pImportDesc->Name == 0) return FALSE; PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)( (PBYTE) hmodCaller + (UINT_PTR)pImportDesc->FirstThunk ); while (pThunk->u1.Function) { PROC* ppfn = (PROC*) &pThunk->u1.Function; BOOL bFound = (*ppfn == pfnCurrent); if (!bFound && (*ppfn > sm_pvMaxAppAddr)) { PBYTE pbInFunc = (PBYTE) *ppfn; // Is this a wrapper (debug thunk) represented by PUSH instruction? if (pbInFunc[0] == cPushOpCode) { ppfn = (PROC*) &pbInFunc[1]; bFound = (*ppfn == pfnCurrent); } } if (bFound) { MEMORY_BASIC_INFORMATION mbi; ::VirtualQuery(ppfn, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); // In order to provide writable access to this part of the // memory we need to change the memory protection if (!::VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &mbi.Protect)) { return FALSE; } // Hook the function. *ppfn = *pfnNew; // Restore the protection back DWORD dwOldProtect; ::VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect); return TRUE; } pThunk++; } pImportDesc++; } } catch(...) { // do nothing } return FALSE; } void CXTPSkinManagerApiHook::InitializeHookManagement() { if (m_bInitialized) return; for (int i = 0; i < (int)m_arrExcludedModules.GetSize(); i++) { CString& strModule = m_arrExcludedModules[i].strModule; if (strModule[strModule.GetLength() - 1] != '*') { m_arrExcludedModules[i].hModule = GetModuleHandle(strModule); } } #define ADDHOOK(Dll, ProcName) \ HookImport(xtpSkinApi##ProcName, Dll, #ProcName, (PROC)&CXTPSkinManagerApiHook::OnHook##ProcName) ADDHOOK("KERNEL32.DLL", LoadLibraryA); ADDHOOK("KERNEL32.DLL", LoadLibraryW); ADDHOOK("KERNEL32.DLL", LoadLibraryExA); ADDHOOK("KERNEL32.DLL", LoadLibraryExW); ADDHOOK("KERNEL32.DLL", GetProcAddress); ADDHOOK("KERNEL32.DLL", GetModuleHandleA); ADDHOOK("KERNEL32.DLL", CreateThread); if (XTPSystemVersion()->IsWin7OrGreater()) { HookImport(xtpSkinApiLoadLibraryEx2W, "API-MS-WIN-CORE-LIBRARYLOADER-L1-1-0.DLL", "LoadLibraryExW", (PROC)&CXTPSkinManagerApiHook::OnHookLoadLibraryEx2W); } ADDHOOK("USER32.DLL", RegisterClassA); ADDHOOK("USER32.DLL", RegisterClassW); if (XTPSkinManager()->GetApplyOptions() & xtpSkinApplyColors) { ADDHOOK("USER32.DLL", GetSysColor); ADDHOOK("USER32.DLL", GetSysColorBrush); ADDHOOK("USER32.DLL", DrawEdge); ADDHOOK("USER32.DLL", FillRect); ADDHOOK("GDI32.DLL", DeleteObject); ADDHOOK("UXTHEME.DLL", OpenThemeData); ADDHOOK("UXTHEME.DLL", DrawThemeBackground); ADDHOOK("UXTHEME.DLL", CloseThemeData); ADDHOOK("UXTHEME.DLL", GetThemeColor); ADDHOOK("UXTHEME.DLL", GetThemeInt); ADDHOOK("UXTHEME.DLL", IsAppThemed); ADDHOOK("UXTHEME.DLL", IsThemeActive); ADDHOOK("UXTHEME.DLL", GetCurrentThemeName); ADDHOOK("UXTHEME.DLL", GetThemeSysBool); ADDHOOK("UXTHEME.DLL", GetThemeSysColor); ADDHOOK("UXTHEME.DLL", GetThemePartSize); ADDHOOK("USER32.DLL", DrawFrameControl); } if (XTPSkinManager()->GetApplyOptions() & xtpSkinApplyFrame) { ADDHOOK("USER32.DLL", SetScrollInfo); ADDHOOK("USER32.DLL", SetScrollPos); ADDHOOK("USER32.DLL", GetScrollInfo); ADDHOOK("USER32.DLL", EnableScrollBar); ADDHOOK("USER32.DLL", DrawMenuBar); } if (XTPSkinManager()->GetApplyOptions() & xtpSkinApplyMetrics) { HookImport(xtpSkinApiSystemParametersInfo, "USER32.DLL", lpszSystemParametersInfo, (PROC)&CXTPSkinManagerApiHook::OnHookSystemParametersInfo); ADDHOOK("USER32.DLL", AdjustWindowRectEx); ADDHOOK("USER32.DLL", AdjustWindowRect); ADDHOOK("USER32.DLL", GetSystemMetrics); } if (XTPSkinManager()->GetApplyOptions() & xtpSkinApplyMenus) { ADDHOOK("USER32.DLL", TrackPopupMenu); ADDHOOK("USER32.DLL", TrackPopupMenuEx); } ADDHOOK("USER32.DLL", DefWindowProcA); ADDHOOK("USER32.DLL", DefWindowProcW); ADDHOOK("USER32.DLL", DefFrameProcA); ADDHOOK("USER32.DLL", DefFrameProcW); ADDHOOK("USER32.DLL", DefDlgProcA); ADDHOOK("USER32.DLL", DefDlgProcW); ADDHOOK("USER32.DLL", DefMDIChildProcA); ADDHOOK("USER32.DLL", DefMDIChildProcW); ADDHOOK("USER32.DLL", CallWindowProcA); ADDHOOK("USER32.DLL", CallWindowProcW); m_bInitialized = TRUE; } void CXTPSkinManagerApiHook::FinalizeHookManagement() { if (!m_bInitialized) return; UnhookAllFunctions(); m_bInitialized = FALSE; } DWORD WINAPI CXTPSkinManagerApiHook::OnHookGetSysColor(int nIndex) { typedef int(WINAPI* LPFNGETSYSCOLOR)(int); CXTPSkinManagerMetrics* pMetrics = XTPSkinManager()->GetMetrics(); if (pMetrics && XTPSkinManager()->IsEnabled() && nIndex < XTP_SKINMETRICS_COLORTABLESIZE && pMetrics->m_clrTheme[nIndex] != -1) return pMetrics->m_clrTheme[nIndex]; PROC pfnOrig = GetOriginalProc(xtpSkinApiGetSysColor); DWORD nResult = pfnOrig ? ((LPFNGETSYSCOLOR)pfnOrig)(nIndex) : GetSysColor(nIndex); return nResult; } BOOL WINAPI CXTPSkinManagerApiHook::OnHookDeleteObject(HGDIOBJ hObject) { typedef BOOL (WINAPI* LPFNDELETEOBJECT)(HGDIOBJ); CXTPSkinManagerMetrics* pMetrics = XTPSkinManager()->GetMetrics(); if (pMetrics && pMetrics->IsMetricObject(hObject)) return FALSE; PROC pfnOrig = GetOriginalProc(xtpSkinApiDeleteObject); return pfnOrig ? ((LPFNDELETEOBJECT)pfnOrig)(hObject) : DeleteObject(hObject); } HBRUSH WINAPI CXTPSkinManagerApiHook::OnHookGetSysColorBrush( int nIndex) { typedef HBRUSH (WINAPI* LPFNGETSYSCOLORBRUSH)(int); CXTPSkinManagerMetrics* pMetrics = XTPSkinManager()->GetMetrics(); if (pMetrics && XTPSkinManager()->IsEnabled() && nIndex > 0 && nIndex < XTP_SKINMETRICS_COLORTABLESIZE && pMetrics->m_brTheme[nIndex]) { return pMetrics->m_brTheme[nIndex]; } PROC pfnOrig = GetOriginalProc(xtpSkinApiGetSysColorBrush); HBRUSH nResult = pfnOrig ? ((LPFNGETSYSCOLORBRUSH)pfnOrig)(nIndex) : GetSysColorBrush(nIndex); return nResult; } int WINAPI CXTPSkinManagerApiHook::OnHookSetScrollPos( HWND hwnd, int nBar, int nPos, BOOL redraw) { typedef int(WINAPI* LPFNSETSCROLLPOS)( HWND hWnd, int nBar, int nPos, BOOL bRedraw); PROC pfnOrig = GetOriginalProc(xtpSkinApiSetScrollPos); if (!pfnOrig) return SetScrollPos(hwnd, nBar, nPos, redraw); CXTPSkinObjectFrame* pFrame = (CXTPSkinObjectFrame*)XTPSkinManager()->Lookup(hwnd); if (!pFrame) return pfnOrig ? ((LPFNSETSCROLLPOS)pfnOrig)(hwnd, nBar, nPos, redraw) : 0; int nResult = pfnOrig ? ((LPFNSETSCROLLPOS)pfnOrig)(hwnd, nBar, nPos, FALSE) : 0; if (redraw) { if (nBar == SB_CTL) InvalidateRect(hwnd, NULL, FALSE); else pFrame->RedrawScrollBar(nBar); } return nResult; } int WINAPI CXTPSkinManagerApiHook::OnHookSetScrollInfo( HWND hwnd, int nBar, LPCSCROLLINFO lpsi, BOOL redraw) { typedef int(WINAPI* LPFNSETSCROLLINFO)(HWND hwnd, int fnBar, LPCSCROLLINFO lpsi, BOOL fRedraw); PROC pfnOrig = GetOriginalProc(xtpSkinApiSetScrollInfo); if (!pfnOrig) return SetScrollInfo(hwnd, nBar, lpsi, redraw); CXTPSkinObjectFrame* pFrame = (CXTPSkinObjectFrame*)XTPSkinManager()->Lookup(hwnd); if (!pFrame || (nBar == SB_CTL) || !redraw) return ((LPFNSETSCROLLINFO)pfnOrig)(hwnd, nBar, lpsi, redraw); int nResult = ((LPFNSETSCROLLINFO)pfnOrig)(hwnd, nBar, lpsi, FALSE); pFrame->RedrawScrollBar(nBar); return nResult; } BOOL WINAPI CXTPSkinManagerApiHook::OnHookEnableScrollBar(HWND hWnd, UINT wSBflags, UINT wArrows) { typedef int(WINAPI* LPFNENABLESCROLLBAR)(HWND hWnd, UINT wSBflags, UINT wArrows); PROC pfnOrig = GetOriginalProc(xtpSkinApiEnableScrollBar); if (!pfnOrig) return EnableScrollBar(hWnd, wSBflags, wArrows); CXTPSkinObjectFrame* pFrame = (CXTPSkinObjectFrame*)XTPSkinManager()->Lookup(hWnd); if (!pFrame) return pfnOrig ? ((LPFNENABLESCROLLBAR)pfnOrig)(hWnd, wSBflags, wArrows) : 0; int nResult = pfnOrig ? ((LPFNENABLESCROLLBAR)pfnOrig)(hWnd, wSBflags, wArrows) : 0; if (wSBflags == SB_BOTH || wSBflags == SB_HORZ) pFrame->RedrawScrollBar(SB_HORZ); if (wSBflags == SB_BOTH || wSBflags == SB_VERT) pFrame->RedrawScrollBar(SB_VERT); return nResult; } BOOL WINAPI CXTPSkinManagerApiHook::OnHookGetScrollInfo(HWND hWnd, int nBar, LPSCROLLINFO lpsi) { typedef BOOL(WINAPI* LPFNGETSCROLLINFO)(HWND hwnd, int nBar, LPCSCROLLINFO lpsi); PROC pfnOrig = GetOriginalProc(xtpSkinApiGetScrollInfo); if (!pfnOrig) return GetScrollInfo(hWnd, nBar, lpsi); BOOL nResult = pfnOrig ? ((LPFNGETSCROLLINFO)pfnOrig)(hWnd, nBar, lpsi) : FALSE; if (lpsi && (lpsi->fMask & SIF_TRACKPOS)) { CXTPSkinObject* pSink = XTPSkinManager()->Lookup(hWnd); if (pSink) { XTP_SKINSCROLLBARTRACKINFO* pSBTrack = ((CXTPSkinObjectFrame*)pSink)->GetScrollBarTrackInfo(); if (pSBTrack && (pSBTrack->nBar == nBar)) { // posNew is in the context of psbiSB's window and bar code lpsi->nTrackPos = pSBTrack->posNew; } } } return nResult; } BOOL CXTPSkinManagerApiHook::IsSystemWindowModule(WNDPROC lpWndProc) { if ((HIWORD((ULONG)(ULONG_PTR)lpWndProc)) == 0xFFFF) return TRUE; static XTP_MODULEINFO miUser32 = {(LPVOID)-1, 0, 0, 0}; if (miUser32.lpBaseOfDll == (LPVOID)-1) { HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL")); miUser32.hModule = hUser32; if (hUser32) { CXTPSkinManagerModuleList moduleList(::GetCurrentProcessId()); moduleList.GetModuleInformation(hUser32, &miUser32); } } if ((LPBYTE)lpWndProc > (LPBYTE)miUser32.lpBaseOfDll && (LPBYTE)lpWndProc < (LPBYTE)miUser32.lpBaseOfDll + miUser32.SizeOfImage) return TRUE; static XTP_MODULEINFO miComCtrl32 = {(LPVOID)-1, 0, (LPVOID)-1, 0}; HMODULE hComCtl32 = GetModuleHandle(_T("COMCTL32.DLL")); if (hComCtl32 && (miComCtrl32.lpBaseOfDll == (LPVOID)-1 || miComCtrl32.hModule != hComCtl32 )) { miComCtrl32.hModule = hComCtl32; CXTPSkinManagerModuleList moduleList(::GetCurrentProcessId()); moduleList.GetModuleInformation(hComCtl32, &miComCtrl32); } if ((LPBYTE)lpWndProc > (LPBYTE)miComCtrl32.lpBaseOfDll && (LPBYTE)lpWndProc < (LPBYTE)miComCtrl32.lpBaseOfDll + miComCtrl32.SizeOfImage) return TRUE; if (XTPSystemVersion()->IsWinXPOrGreater()) { static XTP_MODULEINFO miNtDll = {(LPVOID)-1, 0, 0, 0}; if (miNtDll.lpBaseOfDll == (LPVOID)-1) { HMODULE hNtDLL = GetModuleHandle(_T("NTDLL.DLL")); miNtDll.hModule = hNtDLL; if (hNtDLL) { CXTPSkinManagerModuleList moduleList(::GetCurrentProcessId()); moduleList.GetModuleInformation(hNtDLL, &miNtDll); } } if ((LPBYTE)lpWndProc > (LPBYTE)miNtDll.lpBaseOfDll && (LPBYTE)lpWndProc < (LPBYTE)miNtDll.lpBaseOfDll + miNtDll.SizeOfImage) return TRUE; } return FALSE; } BOOL CXTPSkinManagerApiHook::CallHookDefWindowProc(HWND hWnd, PROC pfnOrig, XTPSkinDefaultProc defProc, LPVOID lpPrev, UINT nMessage, WPARAM& wParam, LPARAM& lParam, LRESULT& lResult) { CXTPSkinManager* pSkinManager = XTPSkinManager(); if (!pSkinManager->IsEnabled()) return FALSE; CXTPSkinObject* pSkinObject = pSkinManager->Lookup(hWnd); if (!pSkinObject || pSkinObject->m_bCustomDraw) return FALSE; if (nMessage == pSkinObject->GetHeadMessage()) return FALSE; if (nMessage == WM_NCDESTROY && !pSkinObject->m_bWindowProcAttached) { pSkinObject->GetSkinManager()->Remove(hWnd, TRUE); return FALSE; } if (defProc == xtpSkinDefaultCallWindowProc && pSkinObject->IsDefWindowProcAvail(nMessage)) { WNDPROC lpWndProc = (WNDPROC)lpPrev; if (IsSystemWindowModule(lpWndProc)) { lpWndProc = 0; } if (lpWndProc != 0 && (!pSkinManager->IsWin9x() || ((DWORD_PTR)lpWndProc < (DWORD_PTR)0x70000000))) { return FALSE; } } MSG& curMsg = AfxGetThreadState()->m_lastSentMsg; MSG oldMsg = curMsg; curMsg.hwnd = hWnd; curMsg.message = nMessage; curMsg.wParam = wParam; curMsg.lParam = lParam; pSkinObject->OnBeginHook(nMessage, defProc, pfnOrig, lpPrev); BOOL bResult = pSkinObject->OnHookDefWindowProc(nMessage, wParam ,lParam, lResult); pSkinObject->OnEndHook(); curMsg = oldMsg; if (bResult) return TRUE; return FALSE; } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookCallWindowProcW(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiCallWindowProcW); if (!pfnOrig) return CallWindowProcW(lpPrevWndFunc, hWnd, Msg, wParam, lParam); LRESULT lResult = 0; if (lpPrevWndFunc && GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultCallWindowProc, lpPrevWndFunc, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNCALLWINDOWPROC)(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); LRESULT bResult = ((LPFNCALLWINDOWPROC)pfnOrig)(lpPrevWndFunc, hWnd, Msg, wParam, lParam); return bResult; } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookCallWindowProcA(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiCallWindowProcA); if (!pfnOrig) return CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam); LRESULT lResult = 0; if (lpPrevWndFunc && GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultCallWindowProc, lpPrevWndFunc, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNCALLWINDOWPROC)(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); LRESULT bResult = ((LPFNCALLWINDOWPROC)pfnOrig)(lpPrevWndFunc, hWnd, Msg, wParam, lParam); return bResult; } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiDefWindowProcA); if (!pfnOrig) return DefWindowProcA(hWnd, Msg, wParam, lParam); LRESULT lResult = 0; if (GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultDefWindowProc, NULL, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNDEFWINDOWPROC)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); return ((LPFNDEFWINDOWPROC)pfnOrig)(hWnd, Msg, wParam, lParam); } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiDefWindowProcW); if (!pfnOrig) return DefWindowProcW(hWnd, Msg, wParam, lParam); LRESULT lResult = 0; if (GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultDefWindowProc, NULL, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNDEFWINDOWPROC)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); return ((LPFNDEFWINDOWPROC)pfnOrig)(hWnd, Msg, wParam, lParam); } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookDefFrameProcA(HWND hWnd, HWND hWndMDIClient, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiDefFrameProcA); if (!pfnOrig) return DefFrameProcA(hWnd, hWndMDIClient, Msg, wParam, lParam); LRESULT lResult = 0; if (GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultDefFrameProc, (LPVOID)hWndMDIClient, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNDEFWINDOWPROC)(HWND hWnd, HWND hWndMDIClient, UINT Msg, WPARAM wParam, LPARAM lParam); return ((LPFNDEFWINDOWPROC)pfnOrig)(hWnd, hWndMDIClient, Msg, wParam, lParam); } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookDefFrameProcW(HWND hWnd, HWND hWndMDIClient, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiDefFrameProcW); if (!pfnOrig) return DefFrameProcW(hWnd, hWndMDIClient, Msg, wParam, lParam); LRESULT lResult = 0; if (GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultDefFrameProc, (LPVOID)hWndMDIClient, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNDEFWINDOWPROC)(HWND hWnd, HWND hWndMDIClient, UINT Msg, WPARAM wParam, LPARAM lParam); return ((LPFNDEFWINDOWPROC)pfnOrig)(hWnd, hWndMDIClient, Msg, wParam, lParam); } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookDefDlgProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiDefDlgProcA); if (!pfnOrig) return DefDlgProcA(hWnd, Msg, wParam, lParam); LRESULT lResult = 0; if (GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultDefDlgProc, NULL, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNDEFWINDOWPROC)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); return ((LPFNDEFWINDOWPROC)pfnOrig)(hWnd, Msg, wParam, lParam); } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookDefDlgProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiDefDlgProcW); if (!pfnOrig) return DefDlgProcW(hWnd, Msg, wParam, lParam); LRESULT lResult = 0; if (GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultDefDlgProc, NULL, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNDEFWINDOWPROC)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); return ((LPFNDEFWINDOWPROC)pfnOrig)(hWnd, Msg, wParam, lParam); } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookDefMDIChildProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiDefMDIChildProcA); if (!pfnOrig) return DefMDIChildProcA(hWnd, Msg, wParam, lParam); LRESULT lResult = 0; if (GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultDefMDIChildProc, NULL, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNDEFWINDOWPROC)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); return ((LPFNDEFWINDOWPROC)pfnOrig)(hWnd, Msg, wParam, lParam); } LRESULT WINAPI CXTPSkinManagerApiHook::OnHookDefMDIChildProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PROC pfnOrig = GetOriginalProc(xtpSkinApiDefMDIChildProcW); if (!pfnOrig) return DefMDIChildProcW(hWnd, Msg, wParam, lParam); LRESULT lResult = 0; if (GetInstance()->CallHookDefWindowProc(hWnd, pfnOrig, xtpSkinDefaultDefMDIChildProc, NULL, Msg, wParam ,lParam, lResult)) { return lResult; } typedef LRESULT (WINAPI* LPFNDEFWINDOWPROC)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); return ((LPFNDEFWINDOWPROC)pfnOrig)(hWnd, Msg, wParam, lParam); } struct XTP_SKINFRAMEWORK_THREADPROCPARAMETER { LPTHREAD_START_ROUTINE lpStartAddress; LPVOID lpParameter; }; DWORD WINAPI CXTPSkinManagerApiHook::ThreadProcHook(LPVOID lpThreadData) { XTP_SKINFRAMEWORK_THREADPROCPARAMETER* parameter = (XTP_SKINFRAMEWORK_THREADPROCPARAMETER*)lpThreadData; LPTHREAD_START_ROUTINE lpStartAddress = parameter->lpStartAddress; LPVOID lpParam = parameter->lpParameter; delete lpThreadData; XTPSkinManager()->EnableCurrentThread(); return (lpStartAddress)(lpParam); } HANDLE STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, UINT_PTR dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) { typedef HANDLE (WINAPI* LPFNCREATETHREAD)(LPSECURITY_ATTRIBUTES lpThreadAttributes, UINT_PTR dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); PROC pfnOrig = GetOriginalProc(xtpSkinApiCreateThread); if (!pfnOrig) return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); if (XTPSkinManager()->IsEnabled() && XTPSkinManager()->GetAutoApplyNewThreads()) { XTP_SKINFRAMEWORK_THREADPROCPARAMETER* pParam = new XTP_SKINFRAMEWORK_THREADPROCPARAMETER; pParam->lpParameter = lpParameter; pParam->lpStartAddress = lpStartAddress; return ((LPFNCREATETHREAD)pfnOrig)(lpThreadAttributes, dwStackSize, ThreadProcHook, pParam, dwCreationFlags, lpThreadId); } return ((LPFNCREATETHREAD)pfnOrig)(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); } ATOM WINAPI CXTPSkinManagerApiHook::OnHookRegisterClassA ( const WNDCLASSA *lpWndClass) { typedef ATOM(WINAPI* LPFNREGISTERCLASSA)(const WNDCLASSA* lpWndClass); PROC pfnOrig = GetOriginalProc(xtpSkinApiRegisterClassA); if (!pfnOrig) return RegisterClassA(lpWndClass); CXTPSkinManagerApiFunction* pDefWindowFunction = NULL; if (lpWndClass && lpWndClass->lpfnWndProc == (WNDPROC)&CXTPSkinManagerApiHook::OnHookDefWindowProcA) { pDefWindowFunction = GetInstance()->GetHookedFunction(xtpSkinApiDefWindowProcA); } if (lpWndClass && lpWndClass->lpfnWndProc == (WNDPROC)&CXTPSkinManagerApiHook::OnHookDefFrameProcA) { pDefWindowFunction = GetInstance()->GetHookedFunction(xtpSkinApiDefFrameProcA); } if (lpWndClass && lpWndClass->lpfnWndProc == (WNDPROC)&CXTPSkinManagerApiHook::OnHookDefMDIChildProcA) { pDefWindowFunction = GetInstance()->GetHookedFunction(xtpSkinApiDefMDIChildProcA); } if (lpWndClass && lpWndClass->lpfnWndProc == (WNDPROC)&CXTPSkinManagerApiHook::OnHookDefDlgProcA) { pDefWindowFunction = GetInstance()->GetHookedFunction(xtpSkinApiDefDlgProcA); } if (pDefWindowFunction) { WNDCLASSA wc; wc = *lpWndClass; wc.lpfnWndProc = (WNDPROC)pDefWindowFunction->m_pfnOrig; return ((LPFNREGISTERCLASSA)pfnOrig)(&wc); } return ((LPFNREGISTERCLASSA)pfnOrig)(lpWndClass); } ATOM WINAPI CXTPSkinManagerApiHook::OnHookRegisterClassW ( const WNDCLASSW *lpWndClass) { typedef ATOM(WINAPI* LPFNREGISTERCLASSW)(const WNDCLASSW* lpWndClass); PROC pfnOrig = GetOriginalProc(xtpSkinApiRegisterClassW); if (!pfnOrig) return RegisterClassW(lpWndClass); CXTPSkinManagerApiFunction* pDefWindowFunction = NULL; if (lpWndClass && lpWndClass->lpfnWndProc == (WNDPROC)&CXTPSkinManagerApiHook::OnHookDefWindowProcW) { pDefWindowFunction = GetInstance()->GetHookedFunction(xtpSkinApiDefWindowProcW); } if (lpWndClass && lpWndClass->lpfnWndProc == (WNDPROC)&CXTPSkinManagerApiHook::OnHookDefFrameProcW) { pDefWindowFunction = GetInstance()->GetHookedFunction(xtpSkinApiDefFrameProcW); } if (lpWndClass && lpWndClass->lpfnWndProc == (WNDPROC)&CXTPSkinManagerApiHook::OnHookDefMDIChildProcW) { pDefWindowFunction = GetInstance()->GetHookedFunction(xtpSkinApiDefMDIChildProcW); } if (lpWndClass && lpWndClass->lpfnWndProc == (WNDPROC)&CXTPSkinManagerApiHook::OnHookDefDlgProcW) { pDefWindowFunction = GetInstance()->GetHookedFunction(xtpSkinApiDefDlgProcW); } if (pDefWindowFunction) { WNDCLASSW wc; wc = *lpWndClass; wc.lpfnWndProc = (WNDPROC)pDefWindowFunction->m_pfnOrig; return ((LPFNREGISTERCLASSW)pfnOrig)(&wc); } return ((LPFNREGISTERCLASSW)pfnOrig)(lpWndClass); } int WINAPI CXTPSkinManagerApiHook::OnHookGetSystemMetrics(int nIndex) { typedef int (WINAPI* LPFNGETSYSTEMMETRICS)(int nIndex); PROC pfnOrig = GetOriginalProc(xtpSkinApiGetSystemMetrics); if (!pfnOrig) return GetSystemMetrics(nIndex); int nResult = ((LPFNGETSYSTEMMETRICS)pfnOrig)(nIndex); CXTPSkinManager* pSkinManager = XTPSkinManager(); if (!pSkinManager->IsEnabled() || !pSkinManager->GetMetrics() || pSkinManager->GetMetrics()->m_bRefreshMetrics) return nResult; if (!pSkinManager->HasApplyOptions(xtpSkinApplyMetrics | xtpSkinApplyColors | xtpSkinApplyFrame)) return nResult; switch (nIndex) { case SM_CYCAPTION: return pSkinManager->GetMetrics()->m_cyCaption; case SM_CYSMCAPTION: return pSkinManager->GetMetrics()->m_cySmallCaption; case SM_CXBORDER: return pSkinManager->GetMetrics()->m_cxBorder; case SM_CYBORDER: return pSkinManager->GetMetrics()->m_cyBorder; case SM_CXHSCROLL: return pSkinManager->GetMetrics()->m_cxHScroll; case SM_CYHSCROLL: return pSkinManager->GetMetrics()->m_cyHScroll; case SM_CXVSCROLL: return pSkinManager->GetMetrics()->m_cxVScroll; case SM_CYVSCROLL: return pSkinManager->GetMetrics()->m_cyVScroll; case SM_CXEDGE: return pSkinManager->GetMetrics()->m_cxEdge; case SM_CYEDGE: return pSkinManager->GetMetrics()->m_cyEdge; } return nResult; } BOOL WINAPI CXTPSkinManagerApiHook::OnHookSystemParametersInfo (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni) { typedef BOOL (WINAPI* LPFNSYSTEMPARAMETERSINFO )(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); PROC pfnOrig = GetOriginalProc(xtpSkinApiSystemParametersInfo); if (!pfnOrig) return SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); BOOL bResult = ((LPFNSYSTEMPARAMETERSINFO)pfnOrig)(uiAction, uiParam, pvParam, fWinIni); CXTPSkinManager* pSkinManager = XTPSkinManager(); if (!pSkinManager->IsEnabled() || pSkinManager->GetMetrics()->m_bRefreshMetrics) return bResult; if (!pSkinManager->HasApplyOptions(xtpSkinApplyMetrics | xtpSkinApplyColors | xtpSkinApplyFrame)) return bResult; if (uiAction == SPI_GETICONTITLELOGFONT && uiParam == sizeof(LOGFONT)) { LOGFONT* pLogFont = (LOGFONT*)pvParam; CXTPSkinManagerSchema* pSchema = XTPSkinManager()->GetSchema(); UINT nSysMetrics = pSchema->GetClassCode(_T("SYSMETRICS")); pSchema->GetFontProperty(nSysMetrics, 0, 0, TMT_ICONTITLEFONT, *pLogFont); } if (uiAction == SPI_GETNONCLIENTMETRICS && uiParam == sizeof(NONCLIENTMETRICS)) { NONCLIENTMETRICS* pncm = (NONCLIENTMETRICS*)pvParam; CXTPSkinManagerSchema* pSchema = XTPSkinManager()->GetSchema(); UINT nSysMetrics = pSchema->GetClassCode(_T("SYSMETRICS")); pSchema->GetFontProperty(nSysMetrics, 0, 0, TMT_MENUFONT, pncm->lfMenuFont); pSchema->GetFontProperty(nSysMetrics, 0, 0, TMT_STATUSFONT, pncm->lfStatusFont); pSchema->GetFontProperty(nSysMetrics, 0, 0, TMT_CAPTIONFONT, pncm->lfCaptionFont); } return bResult; } BOOL CXTPSkinManagerApiHook::AdjustWindowRectExOrig(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle) { typedef BOOL (WINAPI* LPFNADJUSTWINDOWRECTEX)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle); PROC pfnOrig = GetOriginalProc(xtpSkinApiAdjustWindowRectEx); if (pfnOrig) return ((LPFNADJUSTWINDOWRECTEX)pfnOrig)(lpRect, dwStyle, bMenu, dwExStyle); return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle); } BOOL WINAPI CXTPSkinManagerApiHook::OnHookAdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle) { typedef BOOL (WINAPI* LPFNADJUSTWINDOWRECTEX)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle); PROC pfnOrig = GetOriginalProc(xtpSkinApiAdjustWindowRectEx); if (!pfnOrig) return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle); CXTPSkinManager* pSkinManager = XTPSkinManager(); if (pSkinManager->IsEnabled() && lpRect && !bMenu && (pSkinManager->HasApplyOptions(xtpSkinApplyMetrics | xtpSkinApplyFrame)) && (dwStyle & WS_THICKFRAME) && !(((dwStyle & (WS_CAPTION | WS_MAXIMIZE)) == (WS_CAPTION | WS_MAXIMIZE) && ((dwStyle & WS_CHILD) == 0)))) { CRect rcBorders = pSkinManager->GetSchema()->CalcFrameBorders(dwStyle, dwExStyle); lpRect->top -= rcBorders.top; lpRect->left -= rcBorders.left; lpRect->right += rcBorders.right; lpRect->bottom += rcBorders.bottom; return TRUE; } BOOL bResult =((LPFNADJUSTWINDOWRECTEX)pfnOrig)(lpRect, dwStyle, bMenu, dwExStyle); if (bResult && pSkinManager->IsEnabled() && ((dwStyle & WS_CAPTION) == WS_CAPTION) && lpRect && (pSkinManager->HasApplyOptions(xtpSkinApplyMetrics | xtpSkinApplyFrame))) { BOOL bSmallCaption = dwExStyle & WS_EX_TOOLWINDOW; CXTPSkinManagerMetrics* pMetrics = pSkinManager->GetMetrics(); int cyCaption = bSmallCaption ? pMetrics->m_cySmallCaption : pMetrics->m_cyCaption; int cyOsCaption = bSmallCaption ? pMetrics->m_cyOsSmallCaption : pMetrics->m_cyOsCaption; lpRect->top -= cyCaption - cyOsCaption; } return bResult; } BOOL WINAPI CXTPSkinManagerApiHook::OnHookAdjustWindowRect(LPRECT lpRect, DWORD dwStyle, BOOL bMenu) { typedef BOOL (WINAPI* LPFNADJUSTWINDOWRECT)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu); PROC pfnOrig = GetOriginalProc(xtpSkinApiAdjustWindowRect); if (!pfnOrig) return AdjustWindowRect(lpRect, dwStyle, bMenu); CXTPSkinManager* pSkinManager = XTPSkinManager(); if (pSkinManager->IsEnabled() && lpRect && !bMenu && (pSkinManager->HasApplyOptions(xtpSkinApplyMetrics | xtpSkinApplyFrame)) && (dwStyle & WS_THICKFRAME) && !(((dwStyle & (WS_CAPTION | WS_MAXIMIZE)) == (WS_CAPTION | WS_MAXIMIZE)))) { DWORD dwExStyle = 0; if ((dwStyle & WS_THICKFRAME)) dwExStyle = WS_EX_WINDOWEDGE; if (((dwStyle & WS_CAPTION) == WS_DLGFRAME) || ((dwStyle & WS_CAPTION) == WS_CAPTION)) dwExStyle = WS_EX_WINDOWEDGE; CRect rcBorders = pSkinManager->GetSchema()->CalcFrameBorders(dwStyle, dwExStyle); lpRect->top -= rcBorders.top; lpRect->left -= rcBorders.left; lpRect->right += rcBorders.right; lpRect->bottom += rcBorders.bottom; return TRUE; } BOOL bResult =((LPFNADJUSTWINDOWRECT)pfnOrig)(lpRect, dwStyle, bMenu); if (bResult && pSkinManager->IsEnabled() && ((dwStyle & WS_CAPTION) == WS_CAPTION) && lpRect && (pSkinManager->HasApplyOptions(xtpSkinApplyMetrics | xtpSkinApplyFrame))) { BOOL bSmallCaption = FALSE; CXTPSkinManagerMetrics* pMetrics = pSkinManager->GetMetrics(); int cyCaption = bSmallCaption ? pMetrics->m_cySmallCaption : pMetrics->m_cyCaption; int cyOsCaption = bSmallCaption ? pMetrics->m_cyOsSmallCaption : pMetrics->m_cyOsCaption; lpRect->top -= cyCaption - cyOsCaption; } return bResult; } int WINAPI CXTPSkinManagerApiHook::OnHookFillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) { typedef int (WINAPI* LPFNFILLRECT)(HDC hDC, CONST RECT *lprc, HBRUSH hbr); PROC pfnOrig = GetOriginalProc(xtpSkinApiFillRect); if (!pfnOrig) return ::FillRect(hDC, lprc, hbr); CXTPSkinManager* pSkinManager = XTPSkinManager(); if (pSkinManager->IsEnabled() && pSkinManager->GetMetrics() && (DWORD_PTR)hbr > 0 && (DWORD_PTR)hbr < XTP_SKINMETRICS_COLORTABLESIZE) { hbr = pSkinManager->GetMetrics()->m_brTheme[(DWORD_PTR)hbr - 1]; } if (pfnOrig) { return ((LPFNFILLRECT)pfnOrig)(hDC, lprc, hbr); } return 0; } BOOL WINAPI CXTPSkinManagerApiHook::OnHookDrawEdge(HDC hdc, LPRECT lprc, UINT edge, UINT flags) { typedef BOOL (WINAPI* LPFNDRAWEDGE)(HDC, LPRECT, UINT, UINT); PROC pfnOrig = GetOriginalProc(xtpSkinApiDrawEdge); if (!pfnOrig) return DrawEdge(hdc, lprc, edge, flags); if (!XTPSkinManager()->IsEnabled()) return ((LPFNDRAWEDGE)pfnOrig)(hdc, lprc, edge, flags); return XTRSkinFrameworkDrawEdge(hdc, lprc, edge, flags); } BOOL WINAPI CXTPSkinManagerApiHook::OnHookDrawFrameControl(HDC hdc, LPRECT lprc, UINT uType, UINT uState) { typedef BOOL (WINAPI* LPFNDRAWFRAMECONTROL)(HDC, LPRECT, UINT, UINT); PROC pfnOrig = GetOriginalProc(xtpSkinApiDrawFrameControl); if (!pfnOrig) return DrawFrameControl(hdc, lprc, uType, uState); if (!XTPSkinManager()->IsEnabled()) return ((LPFNDRAWFRAMECONTROL)pfnOrig)(hdc, lprc, uType, uState); if (XTRSkinFrameworkDrawFrameControl(hdc, lprc, uType, uState)) return TRUE; return ((LPFNDRAWFRAMECONTROL)pfnOrig)(hdc, lprc, uType, uState); } BOOL WINAPI CXTPSkinManagerApiHook::OnHookDrawMenuBar(HWND hWnd) { typedef BOOL (WINAPI* LPFNDRAWMENUBAR)(HWND hWnd); PROC pfnOrig = GetOriginalProc(xtpSkinApiDrawMenuBar); if (!pfnOrig) return DrawMenuBar(hWnd); CXTPSkinManager* pSkinManager = XTPSkinManager(); CXTPSkinObjectFrame* pFrame = (CXTPSkinObjectFrame*)pSkinManager->Lookup(hWnd); if (pFrame && pSkinManager->IsEnabled() && pSkinManager->HasApplyOptions(xtpSkinApplyFrame)) { return pFrame->DrawMenuBar(); } return ((LPFNDRAWMENUBAR)pfnOrig)(hWnd); } BOOL WINAPI CXTPSkinManagerApiHook::OnHookTrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, CONST RECT *prcRect) { typedef BOOL (WINAPI* LPFNTRACKPOPUPMENU)(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, CONST RECT *prcRect); PROC pfnOrig = GetOriginalProc(xtpSkinApiTrackPopupMenu); if (!pfnOrig) return TrackPopupMenu(hMenu, uFlags, x, y, nReserved, hWnd, prcRect); CXTPSkinManager* pSkinManager = XTPSkinManager(); if (pSkinManager->IsEnabled() && pSkinManager->GetApplyOptions() & xtpSkinApplyMenus) { return CXTPSkinObjectApplicationFrame::TrackPopupMenu(hMenu, uFlags, x, y, hWnd, prcRect); } return ((LPFNTRACKPOPUPMENU)pfnOrig)(hMenu, uFlags, x, y, nReserved, hWnd, prcRect); } BOOL WINAPI CXTPSkinManagerApiHook::OnHookTrackPopupMenuEx(HMENU hMenu, UINT uFlags, int x, int y, HWND hWnd, LPTPMPARAMS lptpParams) { typedef BOOL (WINAPI* LPFNTRACKPOPUPMENUEX)(HMENU hMenu, UINT uFlags, int x, int y, HWND hWnd, LPTPMPARAMS lptpParams); PROC pfnOrig = GetOriginalProc(xtpSkinApiTrackPopupMenuEx); if (!pfnOrig) return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpParams); CXTPSkinManager* pSkinManager = XTPSkinManager(); if (pSkinManager->IsEnabled() && pSkinManager->GetApplyOptions() & xtpSkinApplyMenus) { return CXTPSkinObjectApplicationFrame::TrackPopupMenu(hMenu, uFlags, x, y, hWnd, lptpParams ? &lptpParams->rcExclude : NULL); } return ((LPFNTRACKPOPUPMENUEX)pfnOrig)(hMenu, uFlags, x, y, hWnd, lptpParams); } void CXTPSkinManagerApiHook::HackModuleOnLoad(HMODULE hmod, DWORD dwFlags) { for (int i = 0; i < (int)m_arrExcludedModules.GetSize(); i++) { EXCLUDEDMODULE& em = m_arrExcludedModules[i]; if (em.hModule == NULL && em.strModule[em.strModule.GetLength() - 1] != '*') { em.hModule = GetModuleHandle(em.strModule); } } if (IsModuleExcluded(hmod)) return; if ((hmod != NULL) && ((dwFlags & LOAD_LIBRARY_AS_DATAFILE) == 0)) { for (int i = 0; i < XTP_SKIN_APIHOOKCOUNT; i++) { CXTPSkinManagerApiFunction* pHook = m_arrFunctions[i]; if (pHook) { if (pHook->ReplaceInOneModule(pHook->m_szCalleeModName, pHook->m_pfnOrig, pHook->m_pfnHook, hmod)) { pHook->m_bHooked = TRUE; } } } } } HMODULE WINAPI CXTPSkinManagerApiHook::OnHookLoadLibraryA(LPCSTR pszModuleName) { typedef HMODULE (WINAPI* LPFNLOADLIBRARYA)(LPCSTR pszModuleName); PROC pfnOrig = GetOriginalProc(xtpSkinApiLoadLibraryA); if (!pfnOrig) return ::LoadLibraryA(pszModuleName); HMODULE hmod = ((LPFNLOADLIBRARYA)pfnOrig)(pszModuleName); GetInstance()->HackModuleOnLoad(hmod, 0); return hmod; } HMODULE WINAPI CXTPSkinManagerApiHook::OnHookLoadLibraryW(PCWSTR pszModuleName) { typedef HMODULE (WINAPI* LPFNLOADLIBRARYW)(PCWSTR pszModuleName); PROC pfnOrig = GetOriginalProc(xtpSkinApiLoadLibraryW); if (!pfnOrig) return ::LoadLibraryW(pszModuleName); HMODULE hmod = ((LPFNLOADLIBRARYW)pfnOrig)(pszModuleName); GetInstance()->HackModuleOnLoad(hmod, 0); return hmod; } HMODULE WINAPI CXTPSkinManagerApiHook::OnHookLoadLibraryExA(LPCSTR pszModuleName, HANDLE hFile, DWORD dwFlags) { typedef HMODULE (WINAPI* LPFNLOADLIBRARYEXA)(LPCSTR pszModuleName, HANDLE hFile, DWORD dwFlags); PROC pfnOrig = GetOriginalProc(xtpSkinApiLoadLibraryExA); if (!pfnOrig) return ::LoadLibraryExA(pszModuleName, hFile, dwFlags); HMODULE hmod = ((LPFNLOADLIBRARYEXA)pfnOrig)(pszModuleName, hFile, dwFlags); GetInstance()->HackModuleOnLoad(hmod, dwFlags); return hmod; } HMODULE WINAPI CXTPSkinManagerApiHook::OnHookLoadLibraryExW(PCWSTR pszModuleName, HANDLE hFile, DWORD dwFlags) { typedef HMODULE (WINAPI* LPFNLOADLIBRARYEXW)(PCWSTR pszModuleName, HANDLE hFile, DWORD dwFlags); PROC pfnOrig = GetOriginalProc(xtpSkinApiLoadLibraryExW); if (!pfnOrig) return ::LoadLibraryExW(pszModuleName, hFile, dwFlags); HMODULE hmod = ((LPFNLOADLIBRARYEXW)pfnOrig)(pszModuleName, hFile, dwFlags); GetInstance()->HackModuleOnLoad(hmod, dwFlags); return hmod; } HMODULE WINAPI CXTPSkinManagerApiHook::OnHookLoadLibraryEx2W(PCWSTR pszModuleName, HANDLE hFile, DWORD dwFlags) { typedef HMODULE (WINAPI* LPFNLOADLIBRARYEXW)(PCWSTR pszModuleName, HANDLE hFile, DWORD dwFlags); PROC pfnOrig = GetOriginalProc(xtpSkinApiLoadLibraryEx2W); if (!pfnOrig) return ::LoadLibraryExW(pszModuleName, hFile, dwFlags); HMODULE hmod = ((LPFNLOADLIBRARYEXW)pfnOrig)(pszModuleName, hFile, dwFlags); GetInstance()->HackModuleOnLoad(hmod, dwFlags); return hmod; } HMODULE WINAPI CXTPSkinManagerApiHook::OnHookGetModuleHandleA(LPCSTR lpModuleName) { if (lpModuleName && XTPCompareStringNoCase(lpModuleName, "UxTheme.dll") == 0) if (XTPSkinManager()->GetApplyOptions() & xtpSkinApplyColors) return XTP_UXTHEME_HANDLE; typedef HMODULE (WINAPI* LPFNGETMODULEHANDLEA)(LPCSTR lpModuleName); PROC pfnOrig = GetOriginalProc(xtpSkinApiGetModuleHandleA); if (pfnOrig) return ((LPFNGETMODULEHANDLEA)pfnOrig)(lpModuleName); return ::GetModuleHandleA(lpModuleName); } FARPROC WINAPI CXTPSkinManagerApiHook::OnHookGetProcAddress(HMODULE hmod, PCSTR pszProcName) { if ((DWORD_PTR)pszProcName < 0xFFFF) return GetProcAddressWindows(hmod, pszProcName); CXTPSkinManagerApiFunction* pFuncHook = NULL; if (hmod == XTP_UXTHEME_HANDLE) { pFuncHook = GetInstance()->GetHookedFunction("UXTHEME.DLL", pszProcName); } else { char szFullFileName[MAX_PATH]; ::GetModuleFileNameA(hmod, szFullFileName, MAX_PATH); // We must extract only the name and the extension char* szFileName = strrchr(szFullFileName, '\\'); if (szFileName == NULL) szFileName = szFullFileName; else szFileName = szFileName + 1; if (XTPCompareStringNoCase(szFileName, "UxTheme.dll") == 0) return GetProcAddressWindows(hmod, pszProcName); pFuncHook = GetInstance()->GetHookedFunction(szFileName, pszProcName); } if (pFuncHook) return pFuncHook->m_pfnHook; return GetProcAddressWindows(hmod, pszProcName); } HTHEME STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookOpenThemeData(HWND hWnd, LPCWSTR pszClassList) { CXTPSkinManager* pManager = XTPSkinManager(); if (!pManager->IsEnabled()) return 0; CXTPSkinManagerClass* pClass = pManager->GetSkinClass(pManager->Lookup(hWnd), CString(pszClassList)); return (HTHEME)pClass; } HRESULT STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookDrawThemeBackground(HTHEME hTheme, HDC hDC, int iPartId, int iStateId, const RECT* pRect, const RECT* pClipRect) { if (!hTheme) return E_FAIL; CXTPSkinManagerClass* pClass = XTPSkinManager()->FromHandle(hTheme); if (!pClass) return E_FAIL; HRGN hrgnClip = 0; if (pClipRect && pRect && !EqualRect(pClipRect, pRect)) { hrgnClip = CreateRectRgn(0, 0, 0, 0); if (hrgnClip != NULL) { if (GetClipRgn(hDC, hrgnClip) != 1) { DeleteObject(hrgnClip); hrgnClip = (HRGN)-1; } ::IntersectClipRect(hDC, pClipRect->left, pClipRect->top, pClipRect->right, pClipRect->bottom); } } HRESULT hResult = S_OK; if (!pClass->DrawThemeBackground(CDC::FromHandle(hDC), iPartId, iStateId, pRect)) hResult = E_FAIL; if (hrgnClip != NULL) { if (hrgnClip == (HRGN)-1) { ExtSelectClipRgn(hDC, NULL, RGN_COPY); } else { ExtSelectClipRgn(hDC, hrgnClip, RGN_COPY); DeleteObject(hrgnClip); } } return hResult; } HRESULT STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookCloseThemeData(HTHEME) { return S_OK; } HRESULT STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookGetThemeColor(HTHEME hTheme, int iPartId, int iStateId, int iPropID, COLORREF *pColor) { if (!hTheme) return E_FAIL; CXTPSkinManagerClass* pClass = XTPSkinManager()->FromHandle(hTheme); if (!pClass) return E_FAIL; COLORREF clr = pClass->GetThemeColor(iPartId, iStateId, iPropID); if (clr == (COLORREF)-1) return E_FAIL; *pColor = clr; return S_OK; } HRESULT STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookGetThemeInt(HTHEME hTheme, int iPartId, int iStateId, int iPropID, int *piVal) { if (!hTheme) return E_FAIL; CXTPSkinManagerClass* pClass = XTPSkinManager()->FromHandle(hTheme); if (!pClass) return E_FAIL; CXTPSkinManagerSchemaProperty* pProperty = pClass->GetProperty(XTP_SKINPROPERTY_INT, iPartId, iStateId, iPropID); if (!pProperty) return E_FAIL; if (piVal) *piVal = pProperty->iVal; return S_OK; } BOOL STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookIsThemeActive() { return TRUE; } BOOL STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookIsAppThemed() { return TRUE; } HRESULT STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookGetThemePartSize(HTHEME hTheme, HDC, int iPartId, int iStateId, RECT *pRect, THEMESIZE eSize, SIZE* pSize) { if (!hTheme) return E_FAIL; CXTPSkinManagerClass* pClass = XTPSkinManager()->FromHandle(hTheme); if (!pClass) return E_FAIL; if (!pClass->GetThemePartSize(iPartId, iStateId, pRect, eSize, pSize)) return E_FAIL; return S_OK; } BOOL STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookGetThemeSysBool(HTHEME /*hTheme*/, int iBoolId) { return XTPSkinManager()->GetThemeSysBool(iBoolId); } COLORREF STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookGetThemeSysColor(HTHEME /*hTheme*/, int iColorId) { return XTPSkinManager()->GetThemeSysColor(iColorId); } HRESULT STDAPICALLTYPE CXTPSkinManagerApiHook::OnHookGetCurrentThemeName(LPWSTR pszThemeFileName, int dwMaxNameChars, LPWSTR pszColorBuff, int cchMaxColorChars, LPWSTR /*pszSizeBuff*/, int /*cchMaxSizeChars*/) { CXTPSkinManager* pManager = XTPSkinManager(); if (!pManager->GetResourceFile()) return E_FAIL; if (pszThemeFileName) { CString strThemeFileName = pManager->GetResourceFile()->GetResourcePath(); int nLength = strThemeFileName.GetLength(); if (nLength < dwMaxNameChars) { MBSTOWCS_S(pszThemeFileName, strThemeFileName, nLength + 1); } } if (pszColorBuff) { CString strColorBuff = pManager->GetResourceFile()->GetIniFileName(); strColorBuff.MakeUpper(); if (strColorBuff.Find(_T("METALLIC")) > 0) strColorBuff = _T("metallic"); if (strColorBuff.Find(_T("BLUE")) > 0) strColorBuff = _T("normalcolor"); if (strColorBuff.Find(_T("HOMESTEAD")) > 0) strColorBuff = _T("homestead"); int nLength = strColorBuff.GetLength(); if (nLength < cchMaxColorChars) { MBSTOWCS_S(pszColorBuff, strColorBuff, nLength + 1); } } return S_OK; }