| ... | ... | @@ -13,6 +13,8 @@ |
| 13 | 13 | #include <inttypes.h> |
| 14 | 14 | #include <assert.h> |
| 15 | 15 | |
| 16 | const char *ZIG_WINDOWS_KIT_REG_KEY = "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots"; |
| 17 | |
| 16 | 18 | struct ZigWindowsSDKPrivate { |
| 17 | 19 | ZigWindowsSDK base; |
| 18 | 20 | }; |
| ... | ... | @@ -182,48 +184,42 @@ static ZigFindWindowsSdkError find_10_version(ZigWindowsSDKPrivate *priv) { |
| 182 | 184 | if (priv->base.path10_ptr == nullptr) |
| 183 | 185 | return ZigFindWindowsSdkErrorNone; |
| 184 | 186 | |
| 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 | 	} |
| 227 | 223 | return ZigFindWindowsSdkErrorNone; |
| 228 | 224 | } |
| 229 | 225 | |
| ... | ... | @@ -274,23 +270,32 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) { |
| 274 | 270 | return ZigFindWindowsSdkErrorOutOfMemory; |
| 275 | 271 | } |
| 276 | 272 | |
| 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 | 	} |
| 285 | 283 | |
| 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 | 292 | DWORD tmp_buf_len = MAX_PATH; |
| 288 | 293 | priv->base.path10_ptr = (const char *)calloc(tmp_buf_len, 1); |
| 289 | 294 | if (priv->base.path10_ptr == nullptr) { |
| 290 | 295 | zig_free_windows_sdk(&priv->base); |
| 291 | 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 | 299 | if (rc == ERROR_SUCCESS) { |
| 295 | 300 | priv->base.path10_len = tmp_buf_len - 1; |
| 296 | 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 | 305 | free((void*)priv->base.path10_ptr); |
| 301 | 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 | 322 | DWORD tmp_buf_len = MAX_PATH; |
| 306 | 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 | 325 | zig_free_windows_sdk(&priv->base); |
| 309 | 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 | 329 | if (rc == ERROR_SUCCESS) { |
| 313 | 330 | priv->base.path81_len = tmp_buf_len - 1; |
| 314 | 331 | if (priv->base.path81_ptr[priv->base.path81_len - 1] == '\\') { |