#include "alfpriv.h" #include #if defined(_MSC_VER) && defined(_M_IX86) # pragma warning(push) # pragma warning(disable:4035) // HACK: inline assembly for MSVC 6 // TODO: add version detection to use intrinsic on newer MSVC versions static inline LONG ALF_Compat_InterlockedIncrement(LONG volatile *addend) { __asm { mov eax,1 mov edx,addend lock xadd [edx],eax } } # ifdef InterlockedIncrement # undef InterlockedIncrement # endif # define InterlockedIncrement(d) ALF_Compat_InterlockedIncrement(d) static inline LONG ALF_Compat_InterlockedCompareExchange(volatile LONG *destination, LONG exchange, LONG comparand) { __asm { mov eax,comparand mov ecx,exchange mov edx,destination lock cmpxchg [edx],ecx } } # ifdef InterlockedCompareExchange # undef InterlockedCompareExchange # endif # define InterlockedCompareExchange(d,e,c) ALF_Compat_InterlockedCompareExchange(d,e,c) static inline PVOID ALF_Compat_InterlockedCompareExchangePointer(PVOID volatile *destination, PVOID exchange, PVOID comparand) { return (void*)InterlockedCompareExchange((LONG volatile *)destination, (LONG)exchange, (LONG)comparand); } # ifdef InterlockedCompareExchangePointer # undef InterlockedCompareExchangePointer # endif # define InterlockedCompareExchangePointer(d,e,c) ALF_Compat_InterlockedCompareExchangePointer(d,e,c) # pragma warning(pop) #endif static DWORD ALF_DllGetVersion(const char *dll) { HMODULE hDll = GetModuleHandleA(dll); if (hDll) { DLLGETVERSIONPROC pDllGetVersion; pDllGetVersion = (DLLGETVERSIONPROC)(void*)GetProcAddress(hDll, "DllGetVersion"); if (pDllGetVersion) { DLLVERSIONINFO dvi; HRESULT hr; ZeroMemory(&dvi, sizeof(dvi)); dvi.cbSize = sizeof(dvi); hr = (*pDllGetVersion)(&dvi); if (SUCCEEDED(hr)) { return MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion); } } } return 0; } static int WINAPI ALF_Compat_fallbackGetSystemMetricsForDpi(int nIndex, UINT dpi) { (void)dpi; if (LOBYTE(LOWORD(GetVersion())) < 4) { // old NT does not support several properties, so we fake them switch (nIndex) { case SM_CXEDGE: case SM_CYEDGE: return 2; } } return GetSystemMetrics(nIndex); } static BOOL WINAPI ALF_Compat_fallbackIsAppThemed(void) { return FALSE; } static UINT WINAPI ALF_Compat_fallbackGetDpiForWindow(HWND win) { (void)win; UINT dpi = 0; HDC hdcScreen = GetDC(NULL); if (hdcScreen) { dpi = GetDeviceCaps(hdcScreen, LOGPIXELSY); ReleaseDC(NULL, hdcScreen); } if (!dpi) { dpi = 96; // FIXME! fallback to default DPI } return dpi; } static BOOL WINAPI ALF_Compat_fallbackSystemParametersInfoForDpi(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni, UINT dpi) { (void)dpi; return SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); } static BOOL WINAPI ALF_Compat_fallbackAdjustWindowRectExForDpi(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi) { (void)dpi; return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle); } // FIXME: these support one subclass only, negating the whole point of it typedef struct { ALF_COMPAT_SUBCLASSPROC pfnSubclass; UINT_PTR uIdSubclass; DWORD_PTR dwRefData; UINT runCounter; WNDPROC orig; } ALFWindowSubclassData; static LRESULT CALLBACK ALF_Compat_fallbackSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { ALFWindowSubclassData *data = (ALFWindowSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); LRESULT ret = 0; data->runCounter++; if (data->pfnSubclass) ret = data->pfnSubclass(hwnd, uMsg, wParam, lParam, data->uIdSubclass, data->dwRefData); else ret = CallWindowProc(data->orig, hwnd, uMsg, wParam, lParam); data->runCounter--; if (!data->pfnSubclass && !data->runCounter) { SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); ALF_Free(data); } return ret; } static BOOL WINAPI ALF_Compat_fallbackSetWindowSubclass(HWND hwnd, ALF_COMPAT_SUBCLASSPROC pfnSubclass, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { ALFWindowSubclassData *data = ALF_New(ALFWindowSubclassData, 1); data->pfnSubclass = pfnSubclass; data->uIdSubclass = uIdSubclass; data->dwRefData = dwRefData; data->orig = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data); SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ALF_Compat_fallbackSubclassProc); return TRUE; } static LRESULT WINAPI ALF_Compat_fallbackDefSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { ALFWindowSubclassData *data = (ALFWindowSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); return CallWindowProc(data->orig, hwnd, uMsg, wParam, lParam); } static BOOL WINAPI ALF_Compat_fallbackRemoveWindowSubclass(HWND hwnd, ALF_COMPAT_SUBCLASSPROC pfnSubclass, UINT_PTR uIdSubclass) { (void)pfnSubclass; (void)uIdSubclass; ALFWindowSubclassData *data = (ALFWindowSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); data->pfnSubclass = 0; data->uIdSubclass = 0; SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)data->orig); // can't free it while the subclass is running, possibly in a nested SendMessage // and wants to call DefSubclassProc if (!data->runCounter) { SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); ALF_Free(data); } return TRUE; } long ALF_GetAveCharWidth(HDC hdc) { // see: HOWTO: Calculate Dialog Units When Not Using the System Font SIZE s; GetTextExtentPoint32A(hdc, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &s); return (s.cx / 26 + 1) / 2; } void ALF_UniqueCounterValue(LONG_PTR *pCounterId, LONG_PTR *pCounterValue) { static LONG counter = 0; LONG r = InterlockedIncrement(&counter); *pCounterId = (LONG_PTR)&counter; *pCounterValue = r; } static BOOL WINAPI ALF_Compat_loadIsAppThemed(void) { HMODULE hUxTheme = GetModuleHandleA("uxtheme.dll"); FARPROC p = GetProcAddress(hUxTheme, "IsAppThemed"); if (!p || ALF_DllGetVersion("comctl32.dll") < 0x60000) p = (FARPROC)ALF_Compat_fallbackIsAppThemed; InterlockedCompareExchangePointer((void**)&ALF_Compat_IsAppThemed, (void*)p, (void*)ALF_Compat_loadIsAppThemed); return ALF_Compat_IsAppThemed(); } static UINT WINAPI ALF_Compat_loadGetDpiForWindow(HWND window) { FARPROC p = GetProcAddress(GetModuleHandleA("user32.dll"), "GetDpiForWindow"); if (!p) p = (FARPROC)(void*)ALF_Compat_fallbackGetDpiForWindow; InterlockedCompareExchangePointer((void**)&ALF_Compat_GetDpiForWindow, (void*)p, (void*)ALF_Compat_loadGetDpiForWindow); return ALF_Compat_GetDpiForWindow(window); } static BOOL WINAPI ALF_Compat_loadAdjustWindowRectExForDpi(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi) { FARPROC p = GetProcAddress(GetModuleHandleA("user32.dll"), "AdjustWindowRectExForDpi"); if (!p) p = (FARPROC)(void*)ALF_Compat_fallbackAdjustWindowRectExForDpi; InterlockedCompareExchangePointer((void**)&ALF_Compat_AdjustWindowRectExForDpi, (void*)p, (void*)ALF_Compat_loadAdjustWindowRectExForDpi); return ALF_Compat_AdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi); } static int WINAPI ALF_Compat_loadGetSystemMetricsForDpi(int nIndex, UINT dpi) { void *p = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetSystemMetricsForDpi"); if (!p) p = (void*)ALF_Compat_fallbackGetSystemMetricsForDpi; InterlockedCompareExchangePointer((void**)&ALF_Compat_GetSystemMetricsForDpi, p, (void*)ALF_Compat_loadGetSystemMetricsForDpi); return ALF_Compat_GetSystemMetricsForDpi(nIndex, dpi); } static BOOL WINAPI ALF_Compat_loadSetWindowSubclass(HWND hwnd, ALF_COMPAT_SUBCLASSPROC pfnSubclass, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { HMODULE comctl32 = GetModuleHandleA("comctl32.dll"); void *p = (void*)GetProcAddress(comctl32, "SetWindowSubclass"); if (!p) { p = (void*)GetProcAddress(comctl32, (char*)410); if (!p) { p = (void*)ALF_Compat_fallbackSetWindowSubclass; } } InterlockedCompareExchangePointer((void**)&ALF_Compat_SetWindowSubclass, p, (void*)ALF_Compat_loadSetWindowSubclass); return ALF_Compat_SetWindowSubclass(hwnd, pfnSubclass, uIdSubclass, dwRefData); } static BOOL WINAPI ALF_Compat_loadRemoveWindowSubclass(HWND hwnd, ALF_COMPAT_SUBCLASSPROC pfnSubclass, UINT_PTR uIdSubclass) { HMODULE comctl32 = GetModuleHandleA("comctl32.dll"); void *p = (void*)GetProcAddress(comctl32, "RemoveWindowSubclass"); if (!p) { p = (void*)GetProcAddress(comctl32, (char*)412); if (!p) { p = (void*)ALF_Compat_fallbackRemoveWindowSubclass; } } InterlockedCompareExchangePointer((void**)&ALF_Compat_RemoveWindowSubclass, p, (void*)ALF_Compat_loadRemoveWindowSubclass); return ALF_Compat_RemoveWindowSubclass(hwnd, pfnSubclass, uIdSubclass); } static LRESULT WINAPI ALF_Compat_loadDefSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HMODULE comctl32 = GetModuleHandleA("comctl32.dll"); void *p = (void*)GetProcAddress(comctl32, "DefSubclassProc"); if (!p) { p = (void*)GetProcAddress(comctl32, (char*)413); if (!p) { p = (void*)ALF_Compat_fallbackDefSubclassProc; } } InterlockedCompareExchangePointer((void**)&ALF_Compat_DefSubclassProc, p, (void*)ALF_Compat_loadDefSubclassProc); return ALF_Compat_DefSubclassProc(hwnd, uMsg, wParam, lParam); } static BOOL WINAPI ALF_Compat_loadSystemParametersInfoForDpi(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni, UINT dpi) { void *p = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "SystemParametersInfoForDpi"); if (!p) p = (void*)ALF_Compat_fallbackSystemParametersInfoForDpi; InterlockedCompareExchangePointer((void**)&ALF_Compat_SystemParametersInfoForDpi, p, (void*)ALF_Compat_loadSystemParametersInfoForDpi); return ALF_Compat_SystemParametersInfoForDpi(uiAction, uiParam, pvParam, fWinIni, dpi); } BOOL (WINAPI *ALF_Compat_IsAppThemed)(void) = ALF_Compat_loadIsAppThemed; UINT (WINAPI *ALF_Compat_GetDpiForWindow)(HWND /*window*/) = ALF_Compat_loadGetDpiForWindow; BOOL (WINAPI *ALF_Compat_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT) = ALF_Compat_loadAdjustWindowRectExForDpi; int (WINAPI *ALF_Compat_GetSystemMetricsForDpi)(int, UINT) = ALF_Compat_loadGetSystemMetricsForDpi; BOOL (WINAPI *ALF_Compat_SetWindowSubclass)(HWND, ALF_COMPAT_SUBCLASSPROC, UINT_PTR, DWORD_PTR) = ALF_Compat_loadSetWindowSubclass; LRESULT (WINAPI *ALF_Compat_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM) = ALF_Compat_loadDefSubclassProc; BOOL (WINAPI *ALF_Compat_RemoveWindowSubclass)(HWND, ALF_COMPAT_SUBCLASSPROC, UINT_PTR) = ALF_Compat_loadRemoveWindowSubclass; // FIXME! do Unicode properly for SystemParametersInfoForDpi #ifdef UNICODE BOOL (WINAPI *ALF_Compat_SystemParametersInfoForDpi)(UINT,UINT,PVOID,UINT,UINT) = ALF_Compat_loadSystemParametersInfoForDpi; #else BOOL (WINAPI *ALF_Compat_SystemParametersInfoForDpi)(UINT,UINT,PVOID,UINT,UINT) = ALF_Compat_fallbackSystemParametersInfoForDpi; #endif