Skip to content

Commit dd09fc6

Browse files
committed
Improve compatibility mode detection and patching.
1 parent 32e3347 commit dd09fc6

File tree

8 files changed

+245
-186
lines changed

8 files changed

+245
-186
lines changed

src/d2dx/CompatModeCheck.cpp

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/*
2+
This file is part of D2DX.
3+
4+
Copyright (C) 2021 Bolrog
5+
6+
D2DX is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
D2DX is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with D2DX. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
#include "pch.h"
20+
#include "CompatModeCheck.h"
21+
#include "Utils.h"
22+
23+
using namespace d2dx;
24+
25+
static const wchar_t* CompatModeStrings[] =
26+
{
27+
L"WIN8"
28+
L"WIN7",
29+
L"VISTASP2",
30+
L"VISTASP1",
31+
L"VISTA",
32+
L"WINXPSP3",
33+
L"WINXPSP2",
34+
L"WINXPSP1",
35+
L"WINXP",
36+
L"WIN98",
37+
L"WIN95",
38+
};
39+
40+
const wchar_t* CompatModeKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers";
41+
42+
CompatModeState CheckCompatModeReg(
43+
_In_ HKEY hRootKey,
44+
_In_ const wchar_t* path,
45+
_In_ bool remove)
46+
{
47+
HKEY hKey;
48+
LSTATUS result = RegOpenKeyExW(
49+
hRootKey,
50+
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",
51+
0,
52+
KEY_QUERY_VALUE | KEY_WOW64_64KEY | (remove ? KEY_SET_VALUE : 0),
53+
&hKey);
54+
switch (result)
55+
{
56+
case ERROR_SUCCESS:
57+
break;
58+
59+
case ERROR_FILE_NOT_FOUND:
60+
D2DX_LOG("nf");
61+
return CompatModeState::Disabled;
62+
63+
default:
64+
return CompatModeState::Unknown;
65+
}
66+
67+
std::wstring buf;
68+
DWORD len = MAX_PATH * 2;
69+
do
70+
{
71+
buf.resize(len / 2);
72+
result = RegGetValueW(
73+
hKey,
74+
nullptr,
75+
path,
76+
RRF_RT_REG_SZ,
77+
nullptr,
78+
buf.data(),
79+
&len);
80+
} while (result == ERROR_MORE_DATA);
81+
if (result != ERROR_SUCCESS)
82+
{
83+
RegCloseKey(hKey);
84+
return CompatModeState::Unknown;
85+
}
86+
buf.resize(len / 2);
87+
88+
CompatModeState ret = CompatModeState::Disabled;
89+
switch (result)
90+
{
91+
case ERROR_SUCCESS:
92+
for (const wchar_t* s : CompatModeStrings)
93+
{
94+
std::size_t pos = buf.find(s);
95+
if (pos != std::wstring::npos)
96+
{
97+
ret = CompatModeState::Enabled;
98+
if (remove)
99+
{
100+
std::size_t len = wcslen(s);
101+
if (pos != 0 && buf[pos - 1] == L' ')
102+
{
103+
--pos;
104+
++len;
105+
}
106+
else if (pos + len < buf.length() && buf[pos + len] == L' ')
107+
{
108+
++len;
109+
}
110+
else
111+
{
112+
continue;
113+
}
114+
115+
if (len + 2 == buf.length() && pos == 1 && buf[0] == L'~')
116+
{
117+
result = RegDeleteValueW(hKey, path);
118+
}
119+
else
120+
{
121+
buf.erase(pos, len);
122+
result = RegSetValueExW(
123+
hKey,
124+
path,
125+
0,
126+
REG_SZ,
127+
reinterpret_cast<const BYTE*>(buf.data()),
128+
buf.length() * 2);
129+
}
130+
if (result == ERROR_SUCCESS)
131+
{
132+
ret = CompatModeState::Updated;
133+
}
134+
}
135+
break;
136+
}
137+
}
138+
break;
139+
140+
case ERROR_FILE_NOT_FOUND:
141+
break;
142+
143+
default:
144+
ret = CompatModeState::Unknown;
145+
break;
146+
}
147+
148+
RegCloseKey(hKey);
149+
return ret;
150+
}
151+
152+
_Use_decl_annotations_
153+
CompatModeState d2dx::CheckCompatMode(bool remove)
154+
{
155+
HMODULE module = GetModuleHandleW(nullptr);
156+
std::vector<wchar_t> path;
157+
DWORD result = MAX_PATH / 2;
158+
do
159+
{
160+
result *= 2;
161+
path.resize(result);
162+
result = GetModuleFileNameW(module, path.data(), path.size());
163+
if (result == 0)
164+
{
165+
return CompatModeState::Unknown;
166+
}
167+
} while (result == path.size());
168+
path.resize(static_cast<std::size_t>(result + 1));
169+
170+
CompatModeState machine_state = CheckCompatModeReg(HKEY_LOCAL_MACHINE, path.data(), false);
171+
if (machine_state == CompatModeState::Enabled)
172+
{
173+
return machine_state;
174+
}
175+
176+
CompatModeState user_state = CheckCompatModeReg(HKEY_CURRENT_USER, path.data(), remove);
177+
if (user_state == CompatModeState::Enabled || user_state == CompatModeState::Updated)
178+
{
179+
return user_state;
180+
}
181+
182+
if (machine_state == CompatModeState::Disabled)
183+
{
184+
return machine_state;
185+
}
186+
187+
auto reportedWindowsVersion = d2dx::GetWindowsVersion();
188+
auto realWindowsVersion = d2dx::GetActualWindowsVersion();
189+
190+
return reportedWindowsVersion.major > 6 || (reportedWindowsVersion.major == 6 && reportedWindowsVersion.minor >= 3)
191+
? CompatModeState::Disabled // Reported >= Win10
192+
: realWindowsVersion.major == 0
193+
? CompatModeState::Unknown // No real version
194+
: reportedWindowsVersion.major < realWindowsVersion.major
195+
|| (reportedWindowsVersion.major == realWindowsVersion.major && reportedWindowsVersion.minor < realWindowsVersion.minor)
196+
? CompatModeState::Enabled // reported < real
197+
: CompatModeState::Disabled; // reported >= real
198+
}
Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,12 @@
2020

2121
namespace d2dx
2222
{
23-
class CompatibilityModeDisabler final
24-
{
25-
public:
26-
CompatibilityModeDisabler();
27-
28-
~CompatibilityModeDisabler() noexcept {}
29-
30-
void DisableCompatibilityMode();
31-
32-
private:
33-
bool FixCompatibilityMode(
34-
_In_ HKEY hRootKey,
35-
_In_z_ const wchar_t* filename);
36-
37-
bool HasOsCompatibilityOption(
38-
_In_z_ const wchar_t* options);
23+
enum class CompatModeState {
24+
Enabled,
25+
Updated,
26+
Disabled,
27+
Unknown
3928
};
29+
30+
CompatModeState CheckCompatMode(_In_ bool remove);
4031
}

src/d2dx/CompatibilityModeDisabler.cpp

Lines changed: 0 additions & 147 deletions
This file was deleted.

0 commit comments

Comments
 (0)