authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2023-07-28 23:36:04-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2023-07-28 23:36:04-07:00
log41aaf1e6e8afc72b0541860577631a440083d4c2
tree98448051e34cc58809be3a66ce8ae79e1d76d9de
parent8579f720b045222dfb42d451552528f164740cd2

windows_sdk: Get the latest installed version when using COM

Before, iteration would stop whenever an installation with vcruntime.lib was found, but that may not be the most recent installed version. Instead, we now iterate all installed instances and choose the one with the newest version.

1 files changed, 57 insertions(+), 2 deletions(-)

src/windows_sdk.zig+57-2
......@@ -602,6 +602,16 @@ const MsvcLibDir = struct {
602602 }
603603 defer _ = setup_config.vtable.unknown.Release(setup_config);
604604
605 var setup_helper: *ISetupHelper = undefined;
606 switch (setup_config.vtable.unknown.QueryInterface(
607 setup_config,
608 ISetupHelper.IID,
609 @ptrCast(&setup_helper),
610 )) {
611 windows.S_OK => {},
612 else => return error.PathNotFound,
613 }
614
605615 var all_instances: *IEnumSetupInstances = undefined;
606616 switch (setup_config.vtable.setup_configuration.EnumInstances(setup_config, &all_instances)) {
607617 windows.S_OK => {},
......@@ -610,6 +620,8 @@ const MsvcLibDir = struct {
610620 }
611621 defer _ = all_instances.vtable.unknown.Release(all_instances);
612622
623 var latest_version: windows.ULONGLONG = 0;
624 var latest_version_lib_dir: ?[]const u8 = null;
613625 while (true) {
614626 var cur: *ISetupInstance = undefined;
615627 switch (all_instances.vtable.enum_setup_instances.Next(all_instances, 1, &cur, null)) {
......@@ -620,6 +632,23 @@ const MsvcLibDir = struct {
620632 }
621633 defer _ = cur.vtable.unknown.Release(cur);
622634
635 var installation_version_bstr: windows.BSTR = undefined;
636 switch (cur.vtable.setup_instance.GetInstallationVersion(cur, &installation_version_bstr)) {
637 windows.S_OK => {},
638 windows.E_OUTOFMEMORY => return error.OutOfMemory,
639 else => continue,
640 }
641 defer SysFreeString(installation_version_bstr);
642
643 var parsed_version: windows.ULONGLONG = undefined;
644 switch (setup_helper.vtable.setup_helper.ParseVersion(setup_helper, installation_version_bstr, &parsed_version)) {
645 windows.S_OK => {},
646 else => continue,
647 }
648
649 // We want to end up with the most recent version installed
650 if (parsed_version <= latest_version) continue;
651
623652 var installation_path_bstr: windows.BSTR = undefined;
624653 switch (cur.vtable.setup_instance.GetInstallationPath(cur, &installation_path_bstr)) {
625654 windows.S_OK => {},
......@@ -635,9 +664,14 @@ const MsvcLibDir = struct {
635664 };
636665 errdefer allocator.free(lib_dir_path);
637666
638 return lib_dir_path;
667 if (latest_version_lib_dir) |prev_lib_dir| {
668 allocator.free(prev_lib_dir);
669 }
670 latest_version_lib_dir = lib_dir_path;
671 latest_version = parsed_version;
639672 }
640 return error.PathNotFound;
673
674 return latest_version_lib_dir orelse error.PathNotFound;
641675 }
642676
643677 fn libDirFromInstallationPath(allocator: std.mem.Allocator, installation_path_w: []const u16) error{ OutOfMemory, PathNotFound }![]const u8 {
......@@ -999,6 +1033,27 @@ const ISetupInstance = extern struct {
9991033 }
10001034};
10011035
1036const ISetupHelper = extern struct {
1037 vtable: *extern struct {
1038 unknown: IUnknown.VTable(ISetupHelper),
1039 setup_helper: VTable(ISetupHelper),
1040 },
1041
1042 const IID_Value = windows.GUID.parse("{42b21b78-6192-463e-87bf-d577838f1d5c}");
1043 pub const IID = &IID_Value;
1044
1045 pub fn VTable(comptime T: type) type {
1046 return extern struct {
1047 ParseVersion: *const fn (
1048 self: *T,
1049 pwszVersion: windows.BSTR, // [in]
1050 pullVersion: *windows.ULONGLONG, // [out]
1051 ) callconv(windows.WINAPI) windows.HRESULT,
1052 ParseVersionRange: *anyopaque,
1053 };
1054 }
1055};
1056
10021057const SetupConfiguration = extern struct {
10031058 const CLSID_Value = windows.GUID.parse("{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}");
10041059 pub const CLSID = &CLSID_Value;