diff options
Diffstat (limited to 'alf/alfcompat.cpp')
| -rw-r--r-- | alf/alfcompat.cpp | 107 |
1 files changed, 104 insertions, 3 deletions
diff --git a/alf/alfcompat.cpp b/alf/alfcompat.cpp index 269b9f4..5486b19 100644 --- a/alf/alfcompat.cpp +++ b/alf/alfcompat.cpp @@ -32,6 +32,14 @@ static int WINAPI 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); } @@ -77,6 +85,87 @@ fallbackAdjustWindowRectExForDpi(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD 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 +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); + HeapFree(GetProcessHeap(), 0, data); + } + + return ret; +} + +static BOOL WINAPI +fallbackSetWindowSubclass(HWND hwnd, ALF_COMPAT_SUBCLASSPROC pfnSubclass, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +{ + ALFWindowSubclassData *data = (ALFWindowSubclassData *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ALFWindowSubclassData)); + + 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)fallbackSubclassProc); + + return TRUE; +} + +static LRESULT WINAPI +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 +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); + HeapFree(GetProcessHeap(), 0, data); + } + + return TRUE; +} + ALFCompatFunctions * ALF_CreateCompatFuncTable(void) { @@ -93,9 +182,9 @@ ALF_CreateCompatFuncTable(void) compatfn->entrypoint = fallback; \ } while (0) - COMPAT(comctl32.dll, SetWindowSubclass, 410, NULL); - COMPAT(comctl32.dll, DefSubclassProc, 413, NULL); - COMPAT(comctl32.dll, RemoveWindowSubclass, 412, NULL); + COMPAT(comctl32.dll, SetWindowSubclass, 410, fallbackSetWindowSubclass); + COMPAT(comctl32.dll, DefSubclassProc, 413, fallbackDefSubclassProc); + COMPAT(comctl32.dll, RemoveWindowSubclass, 412, fallbackRemoveWindowSubclass); COMPAT(user32.dll, GetSystemMetricsForDpi, 0, fallbackGetSystemMetricsForDpi); COMPAT(user32.dll, GetDpiForWindow, 0, fallbackGetDpiForWindow); @@ -121,6 +210,18 @@ ALF_CreateCompatFuncTable(void) #undef COMPAT + UINT oldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX); // stop win32s from barking about rpcrt4 + HMODULE rpc = LoadLibraryA("rpcrt4.dll"); + if (rpc) { + // NT always has rpcrt4.dll + compatfn->UuidCreate = (ULONG(WINAPI*)(UUID*))(void*)GetProcAddress(rpc, "UuidCreate"); + } else { + // Win32s always has OLE32 + HMODULE ole32 = LoadLibraryA("ole32.dll"); + compatfn->UuidCreate = (ULONG(WINAPI*)(UUID*))(void*)GetProcAddress(ole32, "CoCreateGuid"); + } + SetErrorMode(oldErrorMode); + return compatfn; } |
