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 @@...@@ -13,6 +13,8 @@
13#include <inttypes.h>13#include <inttypes.h>
14#include <assert.h>14#include <assert.h>
1515
16const char *ZIG_WINDOWS_KIT_REG_KEY = "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots";
17
16struct ZigWindowsSDKPrivate {18struct ZigWindowsSDKPrivate {
17 ZigWindowsSDK base;19 ZigWindowsSDK base;
18};20};
...@@ -182,48 +184,42 @@ static ZigFindWindowsSdkError find_10_version(ZigWindowsSDKPrivate *priv) {...@@ -182,48 +184,42 @@ static ZigFindWindowsSdkError find_10_version(ZigWindowsSDKPrivate *priv) {
182 if (priv->base.path10_ptr == nullptr)184 if (priv->base.path10_ptr == nullptr)
183 return ZigFindWindowsSdkErrorNone;185 return ZigFindWindowsSdkErrorNone;
184186
185 char sdk_lib_dir[4096];187 char reg_query[MAX_PATH] = { 0 };
186 int n = snprintf(sdk_lib_dir, 4096, "%s\\Lib\\*", priv->base.path10_ptr);188 int n = snprintf(reg_query, MAX_PATH, "%s\\%s.0\\Installed Options", ZIG_WINDOWS_KIT_REG_KEY, priv->base.version10_ptr);
187 if (n < 0 || n >= 4096) {189 if (n < 0 || n >= MAX_PATH) {
188 return ZigFindWindowsSdkErrorPathTooLong;190 return ZigFindWindowsSdkErrorPathTooLong;
189 }191 }
190192
191 // enumerate files in sdk path looking for latest version193 HKEY options_key;
192 WIN32_FIND_DATA ffd;194 HRESULT rc;
193 HANDLE hFind = FindFirstFileA(sdk_lib_dir, &ffd);195 rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_query, 0,
194 if (hFind == INVALID_HANDLE_VALUE) {196 KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &options_key);
195 return ZigFindWindowsSdkErrorNotFound;197 if (rc != ERROR_SUCCESS) {
196 }198 return ZigFindWindowsSdkErrorNotFound;
197 int v0 = 0, v1 = 0, v2 = 0, v3 = 0;199 }
198 for (;;) {200
199 if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {201 char *option_name = nullptr;
200 int c0 = 0, c1 = 0, c2 = 0, c3 = 0;202 switch (native_arch) {
201 sscanf(ffd.cFileName, "%d.%d.%d.%d", &c0, &c1, &c2, &c3);203 case NativeArchArm:
202 if (c0 == 10 && c1 == 0 && c2 == 10240 && c3 == 0) {204 option_name = "OptionId.DesktopCPParm";
203 // Microsoft released 26624 as 10240 accidentally.205 break;
204 // https://developer.microsoft.com/en-us/windows/downloads/sdk-archive206 case NativeArchx86_64:
205 c2 = 26624;207 option_name = "OptionId.DesktopCPPx64";
206 }208 break;
207209 case NativeArchi386:
208 if ( (c0 > v0)210 option_name = "OptionId.DesktopCPPx86";
209 || (c0 == v0 && c1 > v1)211 break;
210 || (c0 == v0 && c1 == v1 && c2 > v2)212 default:
211 || (c0 == v0 && c1 == v1 && c2 == v2 && c3 > v3) ) {213 return ZigFindWindowsSdkErrorNotFound;
212 v0 = c0, v1 = c1, v2 = c2, v3 = c3;214 }
213 free((void*)priv->base.version10_ptr);215
214 priv->base.version10_ptr = strdup(ffd.cFileName);216 DWORD val_sz = sizeof(DWORD);
215 if (priv->base.version10_ptr == nullptr) {217 DWORD reg_val = 0;
216 FindClose(hFind);218 DWORD type = REG_DWORD;
217 return ZigFindWindowsSdkErrorOutOfMemory;219 rc = RegQueryValueEx(options_key, option_name, NULL, &type, (LPBYTE)&reg_val, &val_sz);
218 }220 if (rc != ERROR_SUCCESS || reg_val != 1) {
219 }221 return ZigFindWindowsSdkErrorNotFound;
220 }222 }
221 if (FindNextFile(hFind, &ffd) == 0) {
222 FindClose(hFind);
223 break;
224 }
225 }
226 priv->base.version10_len = strlen(priv->base.version10_ptr);
227 return ZigFindWindowsSdkErrorNone;223 return ZigFindWindowsSdkErrorNone;
228}224}
229225
...@@ -274,23 +270,32 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {...@@ -274,23 +270,32 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
274 return ZigFindWindowsSdkErrorOutOfMemory;270 return ZigFindWindowsSdkErrorOutOfMemory;
275 }271 }
276272
277 HKEY key;273 HRESULT rc;
278 HRESULT rc;274
279 rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", 0,275 //note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed
280 KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &key);276 HKEY roots_key;
281 if (rc != ERROR_SUCCESS) {277 rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ZIG_WINDOWS_KIT_REG_KEY, 0,
282 zig_free_windows_sdk(&priv->base);278 KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &roots_key);
283 return ZigFindWindowsSdkErrorNotFound;279 if (rc != ERROR_SUCCESS) {
284 }280 zig_free_windows_sdk(&priv->base);
281 return ZigFindWindowsSdkErrorNotFound;
282 }
285283
286 {284 {
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
287 DWORD tmp_buf_len = MAX_PATH;292 DWORD tmp_buf_len = MAX_PATH;
288 priv->base.path10_ptr = (const char *)calloc(tmp_buf_len, 1);293 priv->base.path10_ptr = (const char *)calloc(tmp_buf_len, 1);
289 if (priv->base.path10_ptr == nullptr) {294 if (priv->base.path10_ptr == nullptr) {
290 zig_free_windows_sdk(&priv->base);295 zig_free_windows_sdk(&priv->base);
291 return ZigFindWindowsSdkErrorOutOfMemory;296 return ZigFindWindowsSdkErrorOutOfMemory;
292 }297 }
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);
294 if (rc == ERROR_SUCCESS) {299 if (rc == ERROR_SUCCESS) {
295 priv->base.path10_len = tmp_buf_len - 1;300 priv->base.path10_len = tmp_buf_len - 1;
296 if (priv->base.path10_ptr[priv->base.path10_len - 1] == '\\') {301 if (priv->base.path10_ptr[priv->base.path10_len - 1] == '\\') {
...@@ -300,7 +305,19 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {...@@ -300,7 +305,19 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
300 free((void*)priv->base.path10_ptr);305 free((void*)priv->base.path10_ptr);
301 priv->base.path10_ptr = nullptr;306 priv->base.path10_ptr = nullptr;
302 }307 }
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 }
303 }319 }
320 find_win10_sdk_done:
304 {321 {
305 DWORD tmp_buf_len = MAX_PATH;322 DWORD tmp_buf_len = MAX_PATH;
306 priv->base.path81_ptr = (const char *)calloc(tmp_buf_len, 1);323 priv->base.path81_ptr = (const char *)calloc(tmp_buf_len, 1);
...@@ -308,7 +325,7 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {...@@ -308,7 +325,7 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
308 zig_free_windows_sdk(&priv->base);325 zig_free_windows_sdk(&priv->base);
309 return ZigFindWindowsSdkErrorOutOfMemory;326 return ZigFindWindowsSdkErrorOutOfMemory;
310 }327 }
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);
312 if (rc == ERROR_SUCCESS) {329 if (rc == ERROR_SUCCESS) {
313 priv->base.path81_len = tmp_buf_len - 1;330 priv->base.path81_len = tmp_buf_len - 1;
314 if (priv->base.path81_ptr[priv->base.path81_len - 1] == '\\') {331 if (priv->base.path81_ptr[priv->base.path81_len - 1] == '\\') {