summaryrefslogtreecommitdiff
path: root/alf/alfcompat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alf/alfcompat.cpp')
-rw-r--r--alf/alfcompat.cpp107
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;
}