diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2019-01-03 23:57:56 +0100 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2019-01-03 23:57:56 +0100 |
| commit | 9c385f9a366da308d2a37ad5deda5d40f9285abb (patch) | |
| tree | 578f6739c8e99f61c0b8747502d8e133e585a7d0 /alf/alfcompat.cpp | |
| parent | cd7b608f0517c1100f79b4a3ec654e4178373506 (diff) | |
extend compatibility to Win95 RTM, NT3.1 and Win32s
Only NT3.51 actually works mostly right, all others suffer from various
kinds of breakage. Running a 3.1-compatible binary on newer windows
enables some kind of compatibility mode with bizarro background brushes
and weirdly sized combo boxes.
Going forward, I'm committed to keep NT3.51 running as long as Win95RTM
is supported. The future of NT3.1 and Win32s support is uncertain.
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; } |
