diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt
index 82125161ad..ca40d993d2 100644
--- a/.github/actions/spelling/expect.txt
+++ b/.github/actions/spelling/expect.txt
@@ -368,6 +368,7 @@ roy
rowids
RRF
rrr
+RTTI
runspace
runtimeclass
ryfu
diff --git a/src/AppInstallerCLI/AppInstallerCLI.vcxproj b/src/AppInstallerCLI/AppInstallerCLI.vcxproj
index 9d23801443..5f969e1d6d 100644
--- a/src/AppInstallerCLI/AppInstallerCLI.vcxproj
+++ b/src/AppInstallerCLI/AppInstallerCLI.vcxproj
@@ -187,6 +187,9 @@
true
true
true
+ false
+ false
+ false
Console
@@ -212,6 +215,7 @@
stdcpp17
true
true
+ false
$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)
@@ -247,6 +251,10 @@
false
false
false
+ false
+ false
+ false
+ false
Console
@@ -295,4 +303,4 @@
-
+
\ No newline at end of file
diff --git a/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj b/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj
index 8be6ac5c12..ad12cf2bfc 100644
--- a/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj
+++ b/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj
@@ -235,6 +235,9 @@
true
true
true
+ false
+ false
+ false
false
@@ -250,6 +253,7 @@
true
true
true
+ false
Windows
@@ -277,6 +281,10 @@
false
false
false
+ false
+ false
+ false
+ false
true
@@ -314,6 +322,10 @@
MultiThreaded
MultiThreaded
MultiThreaded
+ false
+ false
+ false
+ false
true
diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj
index 4746d41c92..89844ea347 100644
--- a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj
+++ b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj
@@ -114,6 +114,7 @@
_NO_ASYNCRTIMP;_DEBUG;%(PreprocessorDefinitions)
$(MSBuildThisFileDirectory)..\AppInstallerCommonCore;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore\Public;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;$(MSBuildThisFileDirectory)..\AppInstallerCommonCore\Public;$(MSBuildThisFileDirectory)..\AppInstallerSharedLib\Public;$(MSBuildThisFileDirectory)..\AppInstallerCLICore\Public;$(MSBuildThisFileDirectory)..\AppInstallerCLICore;$(ProjectDir)..\JsonCppLib;$(ProjectDir)..\cpprestsdk\cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
true
+ false
Console
@@ -132,6 +133,7 @@
_NO_ASYNCRTIMP;WIN32;%(PreprocessorDefinitions)
$(MSBuildThisFileDirectory)..\AppInstallerCommonCore;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore\Public;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;$(MSBuildThisFileDirectory)..\AppInstallerCommonCore\Public;$(MSBuildThisFileDirectory)..\AppInstallerSharedLib\Public;$(MSBuildThisFileDirectory)..\AppInstallerCLICore\Public;$(MSBuildThisFileDirectory)..\AppInstallerCLICore;$(ProjectDir)..\JsonCppLib;$(ProjectDir)..\cpprestsdk\cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
true
+ false
wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;Advapi32.lib;winhttp.lib;onecoreuap.lib;msi.lib;%(AdditionalDependencies)
@@ -153,6 +155,8 @@
$(MSBuildThisFileDirectory)..\AppInstallerCommonCore;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore\Public;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;$(MSBuildThisFileDirectory)..\AppInstallerCommonCore\Public;$(MSBuildThisFileDirectory)..\AppInstallerSharedLib\Public;$(MSBuildThisFileDirectory)..\AppInstallerCLICore\Public;$(MSBuildThisFileDirectory)..\AppInstallerCLICore;$(ProjectDir)..\JsonCppLib;$(ProjectDir)..\cpprestsdk\cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
true
true
+ false
+ false
Console
diff --git a/src/AppInstallerCLITests/TestSource.cpp b/src/AppInstallerCLITests/TestSource.cpp
index d8970960d4..f880e69dff 100644
--- a/src/AppInstallerCLITests/TestSource.cpp
+++ b/src/AppInstallerCLITests/TestSource.cpp
@@ -216,7 +216,7 @@ namespace TestCommon
return IsSameOverride(this, other);
}
- const TestPackage* otherAvailable = dynamic_cast(other);
+ const TestPackage* otherAvailable = PackageCast(other);
if (!otherAvailable ||
InstalledVersion.get() != otherAvailable->InstalledVersion.get() ||
@@ -236,6 +236,16 @@ namespace TestCommon
return true;
}
+ const void* TestPackage::CastTo(IPackageType type) const
+ {
+ if (type == PackageType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
const SourceDetails& TestSource::GetDetails() const
{
return Details;
@@ -263,6 +273,16 @@ namespace TestCommon
}
}
+ void* TestSource::CastTo(AppInstaller::Repository::ISourceType type)
+ {
+ if (type == SourceType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
std::string_view TestSourceFactory::TypeName() const
{
return "*TestSource"sv;
diff --git a/src/AppInstallerCLITests/TestSource.h b/src/AppInstallerCLITests/TestSource.h
index 3dd1160d3a..34205d4c54 100644
--- a/src/AppInstallerCLITests/TestSource.h
+++ b/src/AppInstallerCLITests/TestSource.h
@@ -44,6 +44,8 @@ namespace TestCommon
// IPackage for TestSource
struct TestPackage : public AppInstaller::Repository::IPackage
{
+ static constexpr AppInstaller::Repository::IPackageType PackageType = AppInstaller::Repository::IPackageType::TestPackage;
+
using Manifest = AppInstaller::Manifest::Manifest;
using ISource = AppInstaller::Repository::ISource;
using LocIndString = AppInstaller::Utility::LocIndString;
@@ -68,6 +70,7 @@ namespace TestCommon
std::shared_ptr GetAvailableVersion(const AppInstaller::Repository::PackageVersionKey& versionKey) const override;
bool IsUpdateAvailable(AppInstaller::Repository::PinBehavior) const override;
bool IsSame(const IPackage* other) const override;
+ const void* CastTo(AppInstaller::Repository::IPackageType type) const override;
std::shared_ptr InstalledVersion;
std::vector> AvailableVersions;
@@ -77,11 +80,14 @@ namespace TestCommon
// An ISource implementation for use across the test code.
struct TestSource : public AppInstaller::Repository::ISource, public std::enable_shared_from_this
{
+ static constexpr AppInstaller::Repository::ISourceType SourceType = AppInstaller::Repository::ISourceType::TestSource;
+
const AppInstaller::Repository::SourceDetails& GetDetails() const override;
const std::string& GetIdentifier() const override;
AppInstaller::Repository::SourceInformation GetInformation() const override;
AppInstaller::Repository::SearchResult Search(const AppInstaller::Repository::SearchRequest& request) const override;
+ void* CastTo(AppInstaller::Repository::ISourceType type) override;
AppInstaller::Repository::SourceDetails Details = { "TestSource", "Microsoft.TestSource", "//arg", "", "*TestSource" };
AppInstaller::Repository::SourceInformation Information;
diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj
index cf8f305b92..9c17672dba 100644
--- a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj
+++ b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj
@@ -251,6 +251,9 @@
true
true
true
+ false
+ false
+ false
false
@@ -266,6 +269,7 @@
true
true
true
+ false
Windows
@@ -293,6 +297,10 @@
false
false
false
+ false
+ false
+ false
+ false
true
@@ -330,6 +338,10 @@
MultiThreaded
MultiThreaded
MultiThreaded
+ false
+ false
+ false
+ false
true
@@ -352,6 +364,7 @@
stdcpp17
MultiThreaded
%(AdditionalOptions) /fsanitize-coverage=inline-8bit-counters /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div
+ false
true
diff --git a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj
index f793e21be0..94bd3ff17c 100644
--- a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj
+++ b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj
@@ -234,6 +234,9 @@
true
true
true
+ false
+ false
+ false
false
@@ -249,6 +252,7 @@
true
true
true
+ false
Windows
@@ -276,6 +280,10 @@
false
false
false
+ false
+ false
+ false
+ false
true
@@ -313,6 +321,10 @@
MultiThreaded
MultiThreaded
MultiThreaded
+ false
+ false
+ false
+ false
true
diff --git a/src/AppInstallerRepositoryCore/CompositeSource.cpp b/src/AppInstallerRepositoryCore/CompositeSource.cpp
index 07a894a8db..aed522316b 100644
--- a/src/AppInstallerRepositoryCore/CompositeSource.cpp
+++ b/src/AppInstallerRepositoryCore/CompositeSource.cpp
@@ -421,6 +421,8 @@ namespace AppInstaller::Repository
// we deal with composite packages on CompositePackage.
struct PinnablePackage : public IPackage
{
+ static constexpr IPackageType PackageType = IPackageType::PinnablePackage;
+
PinnablePackage() {}
PinnablePackage(std::shared_ptr package, std::optional pin = {})
: m_package(package), m_pin(pin)
@@ -514,7 +516,7 @@ namespace AppInstaller::Repository
bool IsSame(const IPackage* other) const override
{
- const PinnablePackage* otherAvailable = dynamic_cast(other);
+ const PinnablePackage* otherAvailable = PackageCast(other);
if (otherAvailable)
{
@@ -527,6 +529,16 @@ namespace AppInstaller::Repository
return false;
}
+ const void* CastTo(IPackageType type) const override
+ {
+ if (type == PackageType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
private:
std::string m_sourceId;
std::shared_ptr m_package;
@@ -536,6 +548,8 @@ namespace AppInstaller::Repository
// A composite package for the CompositeSource.
struct CompositePackage : public IPackage
{
+ static constexpr IPackageType PackageType = IPackageType::CompositePackage;
+
CompositePackage(std::shared_ptr installedPackage, std::shared_ptr availablePackage = {})
{
// Grab the installed version's channel to allow for filtering in calls to get available info.
@@ -684,7 +698,7 @@ namespace AppInstaller::Repository
bool IsSame(const IPackage* other) const override
{
- const CompositePackage* otherComposite = dynamic_cast(other);
+ const CompositePackage* otherComposite = PackageCast(other);
if (!otherComposite ||
static_cast(m_installedPackage) != static_cast(otherComposite->m_installedPackage) ||
@@ -710,6 +724,16 @@ namespace AppInstaller::Repository
return true;
}
+ const void* CastTo(IPackageType type) const override
+ {
+ if (type == PackageType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
bool IsSameAsAnyAvailable(const IPackage* other) const
{
if (other)
@@ -962,7 +986,7 @@ namespace AppInstaller::Repository
{
for (auto& match : Matches)
{
- const CompositePackage* compositeMatch = dynamic_cast(match.Package.get());
+ const CompositePackage* compositeMatch = PackageCast(match.Package.get());
if (compositeMatch && compositeMatch->IsSameAsAnyAvailable(availableMatch.Package.get()))
{
if (ResultMatchComparator{}(availableMatch, match))
@@ -1261,6 +1285,16 @@ namespace AppInstaller::Repository
}
}
+ void* CompositeSource::CastTo(ISourceType type)
+ {
+ if (type == SourceType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
void CompositeSource::AddAvailableSource(const Source& source)
{
m_availableSources.emplace_back(source);
diff --git a/src/AppInstallerRepositoryCore/CompositeSource.h b/src/AppInstallerRepositoryCore/CompositeSource.h
index 48828a040c..776074885c 100644
--- a/src/AppInstallerRepositoryCore/CompositeSource.h
+++ b/src/AppInstallerRepositoryCore/CompositeSource.h
@@ -7,6 +7,8 @@ namespace AppInstaller::Repository
{
struct CompositeSource : public ISource
{
+ static constexpr ISourceType SourceType = ISourceType::CompositeSource;
+
explicit CompositeSource(std::string identifier);
CompositeSource(const CompositeSource&) = delete;
@@ -30,6 +32,9 @@ namespace AppInstaller::Repository
// Execute a search on the source.
SearchResult Search(const SearchRequest& request) const override;
+ // Casts to the requested type.
+ void* CastTo(ISourceType type) override;
+
// ~ISource
// Adds an available source to be aggregated.
diff --git a/src/AppInstallerRepositoryCore/ISource.h b/src/AppInstallerRepositoryCore/ISource.h
index df91ed5f8e..2981c37d3a 100644
--- a/src/AppInstallerRepositoryCore/ISource.h
+++ b/src/AppInstallerRepositoryCore/ISource.h
@@ -2,9 +2,22 @@
// Licensed under the MIT License.
#pragma once
#include "Public/winget/RepositorySource.h"
+#include
namespace AppInstaller::Repository
{
+ // To allow for runtime casting from ISource to the specific types, this enum contains all of the ISource implementations.
+ enum class ISourceType
+ {
+ TestSource,
+ ConfigurableTestSource,
+ RestSource,
+ SQLiteIndexSource,
+ CompositeSource,
+ IMutablePackageSource,
+ OpenExceptionProxy,
+ };
+
// Internal interface for interacting with a source from outside of the repository lib.
struct ISource
{
@@ -24,8 +37,30 @@ namespace AppInstaller::Repository
// Execute a search on the source.
virtual SearchResult Search(const SearchRequest& request) const = 0;
+
+ // Gets this object as the requested type, or null if it is not the requested type.
+ virtual void* CastTo(ISourceType type) = 0;
};
+ // Does the equivalent of a dynamic_pointer_cast, but without it to allow RTTI to be disabled.
+ template
+ std::shared_ptr SourceCast(const std::shared_ptr& source)
+ {
+ if (!source)
+ {
+ return {};
+ }
+
+ void* castResult = source->CastTo(SourceType::SourceType);
+
+ if (!castResult)
+ {
+ return {};
+ }
+
+ return std::shared_ptr(source, reinterpret_cast(castResult));
+ }
+
// Internal interface to represents source information; basically SourceDetails but with methods to enable differential behaviors.
struct ISourceReference
{
@@ -54,6 +89,8 @@ namespace AppInstaller::Repository
// Internal interface extension to ISource for databases that can be updated after creation, like InstallingPackages
struct IMutablePackageSource
{
+ static constexpr AppInstaller::Repository::ISourceType SourceType = AppInstaller::Repository::ISourceType::IMutablePackageSource;
+
virtual ~IMutablePackageSource() = default;
// Adds a package version to the source.
diff --git a/src/AppInstallerRepositoryCore/Microsoft/ConfigurableTestSourceFactory.cpp b/src/AppInstallerRepositoryCore/Microsoft/ConfigurableTestSourceFactory.cpp
index 88f9be280c..af8a17ebfe 100644
--- a/src/AppInstallerRepositoryCore/Microsoft/ConfigurableTestSourceFactory.cpp
+++ b/src/AppInstallerRepositoryCore/Microsoft/ConfigurableTestSourceFactory.cpp
@@ -65,6 +65,8 @@ namespace AppInstaller::Repository::Microsoft
// The configurable source itself.
struct ConfigurableTestSource : public ISource
{
+ static constexpr ISourceType SourceType = ISourceType::ConfigurableTestSource;
+
ConfigurableTestSource(const SourceDetails& details, const TestSourceConfiguration& config) :
m_details(details), m_config(config) {}
@@ -78,6 +80,16 @@ namespace AppInstaller::Repository::Microsoft
return {};
}
+ void* CastTo(ISourceType type) override
+ {
+ if (type == SourceType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
private:
SourceDetails m_details;
TestSourceConfiguration m_config;
diff --git a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp
index 1b47d804b4..9465e378ba 100644
--- a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp
+++ b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp
@@ -252,6 +252,8 @@ namespace AppInstaller::Repository::Microsoft
{
using PackageBase::PackageBase;
+ static constexpr IPackageType PackageType = IPackageType::SQLiteAvailablePackage;
+
// Inherited via IPackage
Utility::LocIndString GetProperty(PackageProperty property) const override
{
@@ -308,7 +310,7 @@ namespace AppInstaller::Repository::Microsoft
bool IsSame(const IPackage* other) const override
{
- const AvailablePackage* otherAvailable = dynamic_cast(other);
+ const AvailablePackage* otherAvailable = PackageCast(other);
if (otherAvailable)
{
@@ -317,6 +319,16 @@ namespace AppInstaller::Repository::Microsoft
return false;
}
+
+ const void* CastTo(IPackageType type) const override
+ {
+ if (type == PackageType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
};
// The IPackage impl for SQLiteIndexSource of Installed packages.
@@ -324,6 +336,8 @@ namespace AppInstaller::Repository::Microsoft
{
using PackageBase::PackageBase;
+ static constexpr IPackageType PackageType = IPackageType::SQLiteInstalledPackage;
+
// Inherited via IPackage
Utility::LocIndString GetProperty(PackageProperty property) const override
{
@@ -357,7 +371,7 @@ namespace AppInstaller::Repository::Microsoft
bool IsSame(const IPackage* other) const override
{
- const InstalledPackage* otherInstalled = dynamic_cast(other);
+ const InstalledPackage* otherInstalled = PackageCast(other);
if (otherInstalled)
{
@@ -366,6 +380,16 @@ namespace AppInstaller::Repository::Microsoft
return false;
}
+
+ const void* CastTo(IPackageType type) const override
+ {
+ if (type == PackageType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
};
}
@@ -414,6 +438,16 @@ namespace AppInstaller::Repository::Microsoft
return result;
}
+ void* SQLiteIndexSource::CastTo(ISourceType type)
+ {
+ if (type == SourceType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
bool SQLiteIndexSource::IsSame(const SQLiteIndexSource* other) const
{
return (other && GetIdentifier() == other->GetIdentifier());
@@ -429,6 +463,16 @@ namespace AppInstaller::Repository::Microsoft
{
}
+ void* SQLiteIndexWriteableSource::CastTo(ISourceType type)
+ {
+ if (type == ISourceType::IMutablePackageSource)
+ {
+ return static_cast(this);
+ }
+
+ return SQLiteIndexSource::CastTo(type);
+ }
+
void SQLiteIndexWriteableSource::AddPackageVersion(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath)
{
m_index.AddManifest(manifest, relativePath);
diff --git a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.h b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.h
index b1191940a3..45e438ad02 100644
--- a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.h
+++ b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.h
@@ -13,6 +13,8 @@ namespace AppInstaller::Repository::Microsoft
// A source that holds a SQLiteIndex and lock.
struct SQLiteIndexSource : public std::enable_shared_from_this, public ISource
{
+ static constexpr ISourceType SourceType = ISourceType::SQLiteIndexSource;
+
SQLiteIndexSource(
const SourceDetails& details,
SQLiteIndex&& index,
@@ -39,6 +41,9 @@ namespace AppInstaller::Repository::Microsoft
// Execute a search on the source.
SearchResult Search(const SearchRequest& request) const override;
+ // Casts to the requested type.
+ void* CastTo(ISourceType type) override;
+
// Gets the index.
SQLiteIndex& GetIndex() { return m_index; }
const SQLiteIndex& GetIndex() const { return m_index; }
@@ -69,6 +74,9 @@ namespace AppInstaller::Repository::Microsoft
Synchronization::CrossProcessReaderWriteLock&& lock = {},
bool isInstalledSource = false);
+ // Casts to the requested type.
+ void* CastTo(ISourceType type) override;
+
// Adds a package version to the source.
void AddPackageVersion(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath);
diff --git a/src/AppInstallerRepositoryCore/PackageTrackingCatalog.cpp b/src/AppInstallerRepositoryCore/PackageTrackingCatalog.cpp
index 3717491936..f0a77f28cf 100644
--- a/src/AppInstallerRepositoryCore/PackageTrackingCatalog.cpp
+++ b/src/AppInstallerRepositoryCore/PackageTrackingCatalog.cpp
@@ -161,7 +161,7 @@ namespace AppInstaller::Repository
PackageTrackingCatalog result;
result.m_implementation = std::make_shared();
- result.m_implementation->Source = std::dynamic_pointer_cast(ISourceFactory::GetForType(details.Type)->Create(details)->Open(dummyProgress));
+ result.m_implementation->Source = SourceCast(ISourceFactory::GetForType(details.Type)->Create(details)->Open(dummyProgress));
return result;
}
diff --git a/src/AppInstallerRepositoryCore/Public/winget/RepositorySearch.h b/src/AppInstallerRepositoryCore/Public/winget/RepositorySearch.h
index e0cd95d492..983076b2ed 100644
--- a/src/AppInstallerRepositoryCore/Public/winget/RepositorySearch.h
+++ b/src/AppInstallerRepositoryCore/Public/winget/RepositorySearch.h
@@ -329,6 +329,17 @@ namespace AppInstaller::Repository
ConsiderPins,
};
+ // To allow for runtime casting from IPackage to the specific types, this enum contains all of the IPackage implementations.
+ enum class IPackageType
+ {
+ TestPackage,
+ RestAvailablePackage,
+ SQLiteAvailablePackage,
+ SQLiteInstalledPackage,
+ PinnablePackage,
+ CompositePackage,
+ };
+
// A package, potentially containing information about it's local state and the available versions.
struct IPackage
{
@@ -367,8 +378,30 @@ namespace AppInstaller::Repository
// Determines if the given IPackage refers to the same package as this one.
virtual bool IsSame(const IPackage*) const = 0;
+
+ // Gets this object as the requested type, or null if it is not the requested type.
+ virtual const void* CastTo(IPackageType type) const = 0;
};
+ // Does the equivalent of a dynamic_cast, but without it to allow RTTI to be disabled.
+ // Example usage:
+ // bool IsSame(const IPackage* other) const override
+ // {
+ // const MyPackage* otherAsMyType = PackageCast(other);
+ // ...
+ // }
+ template
+ PackageType PackageCast(const IPackage* package)
+ {
+ static_assert(std::is_pointer_v, "The target type of the PackageCast must be a pointer; use the same type as if this were a dynamic_cast.");
+ if (!package)
+ {
+ return nullptr;
+ }
+ using ActualPackageType = std::remove_pointer_t>;
+ return reinterpret_cast(package->CastTo(ActualPackageType::PackageType));
+ }
+
// A single result from the search.
struct ResultMatch
{
diff --git a/src/AppInstallerRepositoryCore/RepositorySource.cpp b/src/AppInstallerRepositoryCore/RepositorySource.cpp
index 145912e553..b3522a763b 100644
--- a/src/AppInstallerRepositoryCore/RepositorySource.cpp
+++ b/src/AppInstallerRepositoryCore/RepositorySource.cpp
@@ -160,6 +160,8 @@ namespace AppInstaller::Repository
// Carries the exception from an OpenSource call and presents it back at search time.
struct OpenExceptionProxy : public ISource, std::enable_shared_from_this
{
+ static constexpr ISourceType SourceType = ISourceType::OpenExceptionProxy;
+
OpenExceptionProxy(const SourceDetails& details, std::exception_ptr exception) :
m_details(details), m_exception(std::move(exception)) {}
@@ -174,6 +176,16 @@ namespace AppInstaller::Repository
return result;
}
+ void* CastTo(ISourceType type) override
+ {
+ if (type == SourceType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
private:
SourceDetails m_details;
std::exception_ptr m_exception;
@@ -304,7 +316,7 @@ namespace AppInstaller::Repository
{
THROW_HR_IF(E_INVALIDARG, !installedSource.m_source || installedSource.m_isComposite || !availableSource.m_source);
- std::shared_ptr compositeSource = std::dynamic_pointer_cast(availableSource.m_source);
+ std::shared_ptr compositeSource = SourceCast(availableSource.m_source);
if (!compositeSource)
{
@@ -486,7 +498,7 @@ namespace AppInstaller::Repository
{
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_source || !m_isComposite);
- auto compositeSource = std::dynamic_pointer_cast(m_source);
+ auto compositeSource = SourceCast(m_source);
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !compositeSource);
return compositeSource->GetAvailableSources();
@@ -495,7 +507,7 @@ namespace AppInstaller::Repository
void Source::AddPackageVersion(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath)
{
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_source);
- auto writableSource = std::dynamic_pointer_cast(m_source);
+ auto writableSource = SourceCast(m_source);
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !writableSource);
writableSource->AddPackageVersion(manifest, relativePath);
}
@@ -503,7 +515,7 @@ namespace AppInstaller::Repository
void Source::RemovePackageVersion(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath)
{
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_source);
- auto writableSource = std::dynamic_pointer_cast(m_source);
+ auto writableSource = SourceCast(m_source);
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !writableSource);
writableSource->RemovePackageVersion(manifest, relativePath);
}
diff --git a/src/AppInstallerRepositoryCore/Rest/RestSource.cpp b/src/AppInstallerRepositoryCore/Rest/RestSource.cpp
index 492533c739..c97b02c096 100644
--- a/src/AppInstallerRepositoryCore/Rest/RestSource.cpp
+++ b/src/AppInstallerRepositoryCore/Rest/RestSource.cpp
@@ -32,6 +32,8 @@ namespace AppInstaller::Repository::Rest
// The IPackage implementation for Available packages from RestSource.
struct AvailablePackage : public std::enable_shared_from_this, public SourceReference, public IPackage
{
+ static constexpr IPackageType PackageType = IPackageType::RestAvailablePackage;
+
AvailablePackage(const std::shared_ptr& source, IRestClient::Package&& package) :
SourceReference(source), m_package(std::move(package))
{
@@ -87,7 +89,7 @@ namespace AppInstaller::Repository::Rest
bool IsSame(const IPackage* other) const override
{
- const AvailablePackage* otherAvailablePackage = dynamic_cast(other);
+ const AvailablePackage* otherAvailablePackage = PackageCast(other);
if (otherAvailablePackage)
{
@@ -98,6 +100,16 @@ namespace AppInstaller::Repository::Rest
return false;
}
+ const void* CastTo(IPackageType type) const override
+ {
+ if (type == PackageType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
// Helpers for PackageVersion interop
const IRestClient::PackageInfo& PackageInfo() const
{
@@ -445,6 +457,16 @@ namespace AppInstaller::Repository::Rest
return searchResult;
}
+ void* RestSource::CastTo(ISourceType type)
+ {
+ if (type == SourceType)
+ {
+ return this;
+ }
+
+ return nullptr;
+ }
+
const RestClient& RestSource::GetRestClient() const
{
return m_restClient;
diff --git a/src/AppInstallerRepositoryCore/Rest/RestSource.h b/src/AppInstallerRepositoryCore/Rest/RestSource.h
index 13793607aa..c78527a18c 100644
--- a/src/AppInstallerRepositoryCore/Rest/RestSource.h
+++ b/src/AppInstallerRepositoryCore/Rest/RestSource.h
@@ -9,6 +9,8 @@ namespace AppInstaller::Repository::Rest
// A source that holds a RestSource.
struct RestSource : public std::enable_shared_from_this, public ISource
{
+ static constexpr ISourceType SourceType = ISourceType::RestSource;
+
RestSource(const SourceDetails& details, SourceInformation information, RestClient&& restClient);
RestSource(const RestSource&) = delete;
@@ -32,6 +34,9 @@ namespace AppInstaller::Repository::Rest
// Execute a search on the source.
SearchResult Search(const SearchRequest& request) const override;
+ // Casts to the requested type.
+ void* CastTo(ISourceType type) override;
+
// Gets the rest client.
const RestClient& GetRestClient() const;
diff --git a/src/Microsoft.Management.Configuration.OutOfProc/Microsoft.Management.Configuration.OutOfProc.vcxproj b/src/Microsoft.Management.Configuration.OutOfProc/Microsoft.Management.Configuration.OutOfProc.vcxproj
index 9277988914..7b628b5360 100644
--- a/src/Microsoft.Management.Configuration.OutOfProc/Microsoft.Management.Configuration.OutOfProc.vcxproj
+++ b/src/Microsoft.Management.Configuration.OutOfProc/Microsoft.Management.Configuration.OutOfProc.vcxproj
@@ -243,6 +243,9 @@
6001
6001
6001
+ false
+ false
+ false
false
@@ -276,6 +279,7 @@
true
true
6001
+ false
$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)
@@ -315,6 +319,10 @@
6001
6001
6001
+ false
+ false
+ false
+ false
true
@@ -385,6 +393,10 @@
6001
6001
6001
+ false
+ false
+ false
+ false
true
diff --git a/src/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.vcxproj b/src/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.vcxproj
index cb70c82ae9..8a0fead12a 100644
--- a/src/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.vcxproj
+++ b/src/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.vcxproj
@@ -240,6 +240,9 @@
true
true
true
+ false
+ false
+ false
false
@@ -272,6 +275,7 @@
stdcpp17
true
true
+ false
$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)
@@ -307,6 +311,10 @@
false
false
false
+ false
+ false
+ false
+ false
true
@@ -373,6 +381,10 @@
MultiThreaded
MultiThreaded
MultiThreaded
+ false
+ false
+ false
+ false
true
diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj
index 80b051e133..d750136825 100644
--- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj
+++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj
@@ -141,11 +141,19 @@
_DEBUG;%(PreprocessorDefinitions)
$(OutDir)$(TargetName)Debug.pdb
+ false
+ false
+ false
+ false
NDEBUG;%(PreprocessorDefinitions)
+ false
+ false
+ false
+ false
true
@@ -159,6 +167,10 @@
MultiThreaded
MultiThreaded
MultiThreaded
+ false
+ false
+ false
+ false
true
diff --git a/src/PureLib/PureLib.vcxproj b/src/PureLib/PureLib.vcxproj
index e85de9b119..4810c643cc 100644
--- a/src/PureLib/PureLib.vcxproj
+++ b/src/PureLib/PureLib.vcxproj
@@ -145,6 +145,7 @@
Disabled
stdcpp17
pure
+ false
MachineX86
@@ -160,6 +161,7 @@
ProgramDatabase
stdcpp17
pure
+ false
MachineX86
@@ -177,6 +179,7 @@
ProgramDatabase
stdcpp17
pure
+ false
MachineX86
@@ -191,6 +194,7 @@
stdcpp17
pure
TurnOffAllWarnings
+ false
@@ -199,6 +203,7 @@
pure
TurnOffAllWarnings
MultiThreaded
+ false
@@ -206,6 +211,7 @@
stdcpp17
pure
TurnOffAllWarnings
+ false
@@ -214,6 +220,7 @@
pure
TurnOffAllWarnings
MultiThreaded
+ false
@@ -221,6 +228,7 @@
stdcpp17
pure
TurnOffAllWarnings
+ false
@@ -229,6 +237,7 @@
pure
TurnOffAllWarnings
MultiThreaded
+ false
@@ -236,6 +245,7 @@
stdcpp17
pure
TurnOffAllWarnings
+ false
@@ -243,6 +253,7 @@
stdcpp17
pure
TurnOffAllWarnings
+ false
@@ -252,6 +263,7 @@
TurnOffAllWarnings
Default
MultiThreadedDebugDLL
+ false
diff --git a/src/WinGetServer/WinGetServer.vcxproj b/src/WinGetServer/WinGetServer.vcxproj
index 74a83c2950..e12b0d1d36 100644
--- a/src/WinGetServer/WinGetServer.vcxproj
+++ b/src/WinGetServer/WinGetServer.vcxproj
@@ -116,17 +116,21 @@
stdcpp17
stdcpp17
stdcpp17
+ false
+ false
WIN32;%(PreprocessorDefinitions)
stdcpp17
+ false
WIN32;_ARM_;%(PreprocessorDefinitions)
+ false
@@ -139,6 +143,10 @@
stdcpp17
stdcpp17
stdcpp17
+ false
+ false
+ false
+ false
true
diff --git a/src/WinGetUtil/WinGetUtil.vcxproj b/src/WinGetUtil/WinGetUtil.vcxproj
index 6eee1c1f13..2ecabb0618 100644
--- a/src/WinGetUtil/WinGetUtil.vcxproj
+++ b/src/WinGetUtil/WinGetUtil.vcxproj
@@ -177,6 +177,9 @@
true
true
true
+ false
+ false
+ false
false
@@ -211,6 +214,7 @@
false
true
true
+ false
Windows
@@ -248,6 +252,10 @@
false
false
false
+ false
+ false
+ false
+ false
true
diff --git a/src/WindowsPackageManager/WindowsPackageManager.vcxproj b/src/WindowsPackageManager/WindowsPackageManager.vcxproj
index 786d7db7bf..4c3b398b8b 100644
--- a/src/WindowsPackageManager/WindowsPackageManager.vcxproj
+++ b/src/WindowsPackageManager/WindowsPackageManager.vcxproj
@@ -248,6 +248,9 @@
4324
4324
4324
+ false
+ false
+ false
false
@@ -281,6 +284,7 @@
true
true
4324
+ false
$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)
@@ -320,6 +324,10 @@
4324
4324
4324
+ false
+ false
+ false
+ false
true
@@ -390,6 +398,10 @@
4324
4324
4324
+ false
+ false
+ false
+ false
true
diff --git a/src/cpprestsdk/cpprestsdk.vcxproj b/src/cpprestsdk/cpprestsdk.vcxproj
index 832ba93574..5de9adba1f 100644
--- a/src/cpprestsdk/cpprestsdk.vcxproj
+++ b/src/cpprestsdk/cpprestsdk.vcxproj
@@ -241,6 +241,7 @@
stdcpp17
Disabled
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
+ false
MachineX86
@@ -255,6 +256,7 @@
ProgramDatabase
stdcpp17
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
+ false
MachineX86
@@ -272,6 +274,7 @@
stdcpp17
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
MultiThreaded
+ false
MachineX86
@@ -288,6 +291,7 @@
_NO_ASYNCRTIMP;NDEBUG;CPPREST_EXCLUDE_WEBSOCKETS;%(PreprocessorDefinitions)
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
+ false
crypt32.lib;winhttp.lib;
@@ -301,6 +305,7 @@
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
MultiThreaded
+ false
crypt32.lib;winhttp.lib;
@@ -313,6 +318,7 @@
_NO_ASYNCRTIMP;NDEBUG;CPPREST_EXCLUDE_WEBSOCKETS;%(PreprocessorDefinitions)%(PreprocessorDefinitions)
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
+ false
@@ -323,6 +329,7 @@
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
MultiThreaded
+ false
@@ -332,6 +339,7 @@
_NO_ASYNCRTIMP;NDEBUG;CPPREST_EXCLUDE_WEBSOCKETS;%(PreprocessorDefinitions)%(PreprocessorDefinitions)
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
+ false
@@ -342,6 +350,7 @@
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
MultiThreaded
+ false
@@ -351,6 +360,7 @@
_NO_ASYNCRTIMP;_DEBUG;CPPREST_EXCLUDE_WEBSOCKETS;%(PreprocessorDefinitions)%(PreprocessorDefinitions)
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
+ false
@@ -360,6 +370,7 @@
_NO_ASYNCRTIMP;_DEBUG;CPPREST_EXCLUDE_WEBSOCKETS;%(PreprocessorDefinitions)%(PreprocessorDefinitions)
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
+ false
@@ -369,6 +380,7 @@
_NO_ASYNCRTIMP;_DEBUG;CPPREST_EXCLUDE_WEBSOCKETS;%(PreprocessorDefinitions)
TurnOffAllWarnings
$(ProjectDir)cpprestsdk\Release\src\pch;$(ProjectDir)cpprestsdk\Release\include;%(AdditionalIncludeDirectories)
+ false
crypt32.lib;winhttp.lib;