authorgravatar for rsdimenus@gmail.comRyan Saunderson <rsdimenus@gmail.com> 2018-10-24 15:14:16-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-10-24 16:14:16-04:00
log73ab0afaddb6fd71a800b11b3bf807c8ca37a9e8
tree89c71c8dee19f2c46311c183c987942cba90ea95
parent63f9769e802894cc43e2e19d97918b1a99382d25

Bug fixes in WinSDK detection (#1665)

* fixed detecting the latest installed version of the windows sdk & related tests

1 files changed, 69 insertions(+), 52 deletions(-)

src/windows_sdk.cpp+69-52
......@@ -13,6 +13,8 @@
1313#include <inttypes.h>
1414#include <assert.h>
1515
16const char *ZIG_WINDOWS_KIT_REG_KEY = "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots";
17
1618struct 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,7 +305,19 @@ 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);
......@@ -308,7 +325,7 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
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] == '\\') {