| ... | ... | @@ -587,6 +587,31 @@ pub const Installation = struct { |
| 587 | 587 | }; |
| 588 | 588 | |
| 589 | 589 | const MsvcLibDir = struct { |
| 590 | fn findInstancesDirViaSetup(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { |
| 591 | const vs_setup_key_path = "SOFTWARE\\Microsoft\\VisualStudio\\Setup"; |
| 592 | const vs_setup_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, vs_setup_key_path) catch |err| switch (err) { |
| 593 | error.KeyNotFound => return error.PathNotFound, |
| 594 | }; |
| 595 | defer vs_setup_key.closeKey(); |
| 596 | |
| 597 | const packages_path = vs_setup_key.getString(allocator, "", "CachePath") catch |err| switch (err) { |
| 598 | error.NotAString, |
| 599 | error.ValueNameNotFound, |
| 600 | error.StringNotFound, |
| 601 | => return error.PathNotFound, |
| 602 | |
| 603 | error.OutOfMemory => return error.OutOfMemory, |
| 604 | }; |
| 605 | defer allocator.free(packages_path); |
| 606 | |
| 607 | if (!std.fs.path.isAbsolute(packages_path)) return error.PathNotFound; |
| 608 | |
| 609 | const instances_path = try std.fs.path.join(allocator, &.{ packages_path, "_Instances" }); |
| 610 | defer allocator.free(instances_path); |
| 611 | |
| 612 | return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound; |
| 613 | } |
| 614 | |
| 590 | 615 | fn findInstancesDirViaCLSID(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { |
| 591 | 616 | const setup_configuration_clsid = "{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}"; |
| 592 | 617 | const setup_config_key = RegistryWtf8.openKey(windows.HKEY_CLASSES_ROOT, "CLSID\\" ++ setup_configuration_clsid) catch |err| switch (err) { |
| ... | ... | @@ -604,6 +629,8 @@ const MsvcLibDir = struct { |
| 604 | 629 | }; |
| 605 | 630 | defer allocator.free(dll_path); |
| 606 | 631 | |
| 632 | if (!std.fs.path.isAbsolute(dll_path)) return error.PathNotFound; |
| 633 | |
| 607 | 634 | var path_it = std.fs.path.componentIterator(dll_path) catch return error.PathNotFound; |
| 608 | 635 | // the .dll filename |
| 609 | 636 | _ = path_it.last(); |
| ... | ... | @@ -622,22 +649,40 @@ const MsvcLibDir = struct { |
| 622 | 649 | } |
| 623 | 650 | |
| 624 | 651 | fn findInstancesDir(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { |
| 625 | | // First try to get the path from the .dll that would have been |
| 652 | // First, try getting the packages cache path from the registry. |
| 653 | // This only seems to exist when the path is different from the default. |
| 654 | method1: { |
| 655 | return findInstancesDirViaSetup(allocator) catch |err| switch (err) { |
| 656 | error.OutOfMemory => |e| return e, |
| 657 | error.PathNotFound => break :method1, |
| 658 | }; |
| 659 | } |
| 660 | // Otherwise, try to get the path from the .dll that would have been |
| 626 | 661 | // loaded via COM for SetupConfiguration. |
| 627 | | return findInstancesDirViaCLSID(allocator) catch |orig_err| { |
| 628 | | // If that can't be found, fall back to manually appending |
| 629 | | // `Microsoft\VisualStudio\Packages\_Instances` to %PROGRAMDATA% |
| 662 | method2: { |
| 663 | return findInstancesDirViaCLSID(allocator) catch |err| switch (err) { |
| 664 | error.OutOfMemory => |e| return e, |
| 665 | error.PathNotFound => break :method2, |
| 666 | }; |
| 667 | } |
| 668 | // If that can't be found, fall back to manually appending |
| 669 | // `Microsoft\VisualStudio\Packages\_Instances` to %PROGRAMDATA% |
| 670 | method3: { |
| 630 | 671 | const program_data = std.process.getEnvVarOwned(allocator, "PROGRAMDATA") catch |err| switch (err) { |
| 631 | 672 | error.OutOfMemory => |e| return e, |
| 632 | | else => return orig_err, |
| 673 | error.InvalidWtf8 => unreachable, |
| 674 | error.EnvironmentVariableNotFound => break :method3, |
| 633 | 675 | }; |
| 634 | 676 | defer allocator.free(program_data); |
| 635 | 677 | |
| 678 | if (!std.fs.path.isAbsolute(program_data)) break :method3; |
| 679 | |
| 636 | 680 | const instances_path = try std.fs.path.join(allocator, &.{ program_data, "Microsoft", "VisualStudio", "Packages", "_Instances" }); |
| 637 | 681 | defer allocator.free(instances_path); |
| 638 | 682 | |
| 639 | | return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return orig_err; |
| 640 | | }; |
| 683 | return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch break :method3; |
| 684 | } |
| 685 | return error.PathNotFound; |
| 641 | 686 | } |
| 642 | 687 | |
| 643 | 688 | /// Intended to be equivalent to `ISetupHelper.ParseVersion` |