Skip to content

Commit 73ab0af

Browse files
dimenusandrewrk
authored andcommitted
Bug fixes in WinSDK detection (#1665)
* fixed detecting the latest installed version of the windows sdk & related tests
1 parent 63f9769 commit 73ab0af

File tree

1 file changed

+69
-52
lines changed

1 file changed

+69
-52
lines changed

src/windows_sdk.cpp

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <inttypes.h>
1414
#include <assert.h>
1515

16+
const char *ZIG_WINDOWS_KIT_REG_KEY = "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots";
17+
1618
struct ZigWindowsSDKPrivate {
1719
ZigWindowsSDK base;
1820
};
@@ -182,48 +184,42 @@ static ZigFindWindowsSdkError find_10_version(ZigWindowsSDKPrivate *priv) {
182184
if (priv->base.path10_ptr == nullptr)
183185
return ZigFindWindowsSdkErrorNone;
184186

185-
char sdk_lib_dir[4096];
186-
int n = snprintf(sdk_lib_dir, 4096, "%s\\Lib\\*", priv->base.path10_ptr);
187-
if (n < 0 || n >= 4096) {
188-
return ZigFindWindowsSdkErrorPathTooLong;
189-
}
190-
191-
// enumerate files in sdk path looking for latest version
192-
WIN32_FIND_DATA ffd;
193-
HANDLE hFind = FindFirstFileA(sdk_lib_dir, &ffd);
194-
if (hFind == INVALID_HANDLE_VALUE) {
195-
return ZigFindWindowsSdkErrorNotFound;
196-
}
197-
int v0 = 0, v1 = 0, v2 = 0, v3 = 0;
198-
for (;;) {
199-
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
200-
int c0 = 0, c1 = 0, c2 = 0, c3 = 0;
201-
sscanf(ffd.cFileName, "%d.%d.%d.%d", &c0, &c1, &c2, &c3);
202-
if (c0 == 10 && c1 == 0 && c2 == 10240 && c3 == 0) {
203-
// Microsoft released 26624 as 10240 accidentally.
204-
// https://developer.microsoft.com/en-us/windows/downloads/sdk-archive
205-
c2 = 26624;
206-
}
207-
208-
if ( (c0 > v0)
209-
|| (c0 == v0 && c1 > v1)
210-
|| (c0 == v0 && c1 == v1 && c2 > v2)
211-
|| (c0 == v0 && c1 == v1 && c2 == v2 && c3 > v3) ) {
212-
v0 = c0, v1 = c1, v2 = c2, v3 = c3;
213-
free((void*)priv->base.version10_ptr);
214-
priv->base.version10_ptr = strdup(ffd.cFileName);
215-
if (priv->base.version10_ptr == nullptr) {
216-
FindClose(hFind);
217-
return ZigFindWindowsSdkErrorOutOfMemory;
218-
}
219-
}
220-
}
221-
if (FindNextFile(hFind, &ffd) == 0) {
222-
FindClose(hFind);
223-
break;
224-
}
225-
}
226-
priv->base.version10_len = strlen(priv->base.version10_ptr);
187+
char reg_query[MAX_PATH] = { 0 };
188+
int n = snprintf(reg_query, MAX_PATH, "%s\\%s.0\\Installed Options", ZIG_WINDOWS_KIT_REG_KEY, priv->base.version10_ptr);
189+
if (n < 0 || n >= MAX_PATH) {
190+
return ZigFindWindowsSdkErrorPathTooLong;
191+
}
192+
193+
HKEY options_key;
194+
HRESULT rc;
195+
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_query, 0,
196+
KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &options_key);
197+
if (rc != ERROR_SUCCESS) {
198+
return ZigFindWindowsSdkErrorNotFound;
199+
}
200+
201+
char *option_name = nullptr;
202+
switch (native_arch) {
203+
case NativeArchArm:
204+
option_name = "OptionId.DesktopCPParm";
205+
break;
206+
case NativeArchx86_64:
207+
option_name = "OptionId.DesktopCPPx64";
208+
break;
209+
case NativeArchi386:
210+
option_name = "OptionId.DesktopCPPx86";
211+
break;
212+
default:
213+
return ZigFindWindowsSdkErrorNotFound;
214+
}
215+
216+
DWORD val_sz = sizeof(DWORD);
217+
DWORD reg_val = 0;
218+
DWORD type = REG_DWORD;
219+
rc = RegQueryValueEx(options_key, option_name, NULL, &type, (LPBYTE)&reg_val, &val_sz);
220+
if (rc != ERROR_SUCCESS || reg_val != 1) {
221+
return ZigFindWindowsSdkErrorNotFound;
222+
}
227223
return ZigFindWindowsSdkErrorNone;
228224
}
229225

@@ -274,23 +270,32 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
274270
return ZigFindWindowsSdkErrorOutOfMemory;
275271
}
276272

277-
HKEY key;
278-
HRESULT rc;
279-
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", 0,
280-
KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &key);
281-
if (rc != ERROR_SUCCESS) {
282-
zig_free_windows_sdk(&priv->base);
283-
return ZigFindWindowsSdkErrorNotFound;
284-
}
273+
HRESULT rc;
274+
275+
//note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed
276+
HKEY roots_key;
277+
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ZIG_WINDOWS_KIT_REG_KEY, 0,
278+
KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &roots_key);
279+
if (rc != ERROR_SUCCESS) {
280+
zig_free_windows_sdk(&priv->base);
281+
return ZigFindWindowsSdkErrorNotFound;
282+
}
285283

286284
{
285+
HKEY v10_key;
286+
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v10.0", 0,
287+
KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &v10_key);
288+
if (rc != ERROR_SUCCESS) {
289+
goto find_win10_sdk_done;
290+
}
291+
287292
DWORD tmp_buf_len = MAX_PATH;
288293
priv->base.path10_ptr = (const char *)calloc(tmp_buf_len, 1);
289294
if (priv->base.path10_ptr == nullptr) {
290295
zig_free_windows_sdk(&priv->base);
291296
return ZigFindWindowsSdkErrorOutOfMemory;
292297
}
293-
rc = RegQueryValueEx(key, "KitsRoot10", NULL, NULL, (LPBYTE)priv->base.path10_ptr, &tmp_buf_len);
298+
rc = RegQueryValueEx(v10_key, "InstallationFolder", NULL, NULL, (LPBYTE)priv->base.path10_ptr, &tmp_buf_len);
294299
if (rc == ERROR_SUCCESS) {
295300
priv->base.path10_len = tmp_buf_len - 1;
296301
if (priv->base.path10_ptr[priv->base.path10_len - 1] == '\\') {
@@ -300,15 +305,27 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
300305
free((void*)priv->base.path10_ptr);
301306
priv->base.path10_ptr = nullptr;
302307
}
308+
309+
priv->base.version10_ptr = (const char*)calloc(tmp_buf_len, 1);
310+
rc = RegQueryValueEx(v10_key, "ProductVersion", NULL, NULL, (LPBYTE)priv->base.version10_ptr, &tmp_buf_len);
311+
if (rc == ERROR_SUCCESS) {
312+
size_t orig_len = priv->base.version10_len;
313+
snprintf((char*)priv->base.version10_ptr, MAX_PATH, "%s.0", priv->base.version10_ptr);
314+
priv->base.version10_len = tmp_buf_len - 1 + 2; // note(dimenus): Microsoft doesn't include the .0 in the ProductVersion key....
315+
} else {
316+
free((void*)priv->base.version10_ptr);
317+
priv->base.version10_ptr = nullptr;
318+
}
303319
}
320+
find_win10_sdk_done:
304321
{
305322
DWORD tmp_buf_len = MAX_PATH;
306323
priv->base.path81_ptr = (const char *)calloc(tmp_buf_len, 1);
307324
if (priv->base.path81_ptr == nullptr) {
308325
zig_free_windows_sdk(&priv->base);
309326
return ZigFindWindowsSdkErrorOutOfMemory;
310327
}
311-
rc = RegQueryValueEx(key, "KitsRoot81", NULL, NULL, (LPBYTE)priv->base.path81_ptr, &tmp_buf_len);
328+
rc = RegQueryValueEx(roots_key, "KitsRoot81", NULL, NULL, (LPBYTE)priv->base.path81_ptr, &tmp_buf_len);
312329
if (rc == ERROR_SUCCESS) {
313330
priv->base.path81_len = tmp_buf_len - 1;
314331
if (priv->base.path81_ptr[priv->base.path81_len - 1] == '\\') {

0 commit comments

Comments
 (0)