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 {...@@ -602,6 +602,16 @@ const MsvcLibDir = struct {
602 }602 }
603 defer _ = setup_config.vtable.unknown.Release(setup_config);603 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
605 var all_instances: *IEnumSetupInstances = undefined;615 var all_instances: *IEnumSetupInstances = undefined;
606 switch (setup_config.vtable.setup_configuration.EnumInstances(setup_config, &all_instances)) {616 switch (setup_config.vtable.setup_configuration.EnumInstances(setup_config, &all_instances)) {
607 windows.S_OK => {},617 windows.S_OK => {},
...@@ -610,6 +620,8 @@ const MsvcLibDir = struct {...@@ -610,6 +620,8 @@ const MsvcLibDir = struct {
610 }620 }
611 defer _ = all_instances.vtable.unknown.Release(all_instances);621 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;
613 while (true) {625 while (true) {
614 var cur: *ISetupInstance = undefined;626 var cur: *ISetupInstance = undefined;
615 switch (all_instances.vtable.enum_setup_instances.Next(all_instances, 1, &cur, null)) {627 switch (all_instances.vtable.enum_setup_instances.Next(all_instances, 1, &cur, null)) {
...@@ -620,6 +632,23 @@ const MsvcLibDir = struct {...@@ -620,6 +632,23 @@ const MsvcLibDir = struct {
620 }632 }
621 defer _ = cur.vtable.unknown.Release(cur);633 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
623 var installation_path_bstr: windows.BSTR = undefined;652 var installation_path_bstr: windows.BSTR = undefined;
624 switch (cur.vtable.setup_instance.GetInstallationPath(cur, &installation_path_bstr)) {653 switch (cur.vtable.setup_instance.GetInstallationPath(cur, &installation_path_bstr)) {
625 windows.S_OK => {},654 windows.S_OK => {},
...@@ -635,9 +664,14 @@ const MsvcLibDir = struct {...@@ -635,9 +664,14 @@ const MsvcLibDir = struct {
635 };664 };
636 errdefer allocator.free(lib_dir_path);665 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;
639 }672 }
640 return error.PathNotFound;673
674 return latest_version_lib_dir orelse error.PathNotFound;
641 }675 }
642676
643 fn libDirFromInstallationPath(allocator: std.mem.Allocator, installation_path_w: []const u16) error{ OutOfMemory, PathNotFound }![]const u8 {677 fn libDirFromInstallationPath(allocator: std.mem.Allocator, installation_path_w: []const u16) error{ OutOfMemory, PathNotFound }![]const u8 {
...@@ -999,6 +1033,27 @@ const ISetupInstance = extern struct {...@@ -999,6 +1033,27 @@ const ISetupInstance = extern struct {
999 }1033 }
1000};1034};
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
1002const SetupConfiguration = extern struct {1057const SetupConfiguration = extern struct {
1003 const CLSID_Value = windows.GUID.parse("{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}");1058 const CLSID_Value = windows.GUID.parse("{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}");
1004 pub const CLSID = &CLSID_Value;1059 pub const CLSID = &CLSID_Value;