Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into admin-loadmod
Browse files Browse the repository at this point in the history
  • Loading branch information
msftrubengu committed Oct 23, 2023
2 parents d720753 + a32e114 commit de53456
Show file tree
Hide file tree
Showing 177 changed files with 3,262 additions and 685 deletions.
5 changes: 5 additions & 0 deletions .github/actions/spelling/allow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ etstandard
ETW
EULA
EVENTTAG
EWX
exe
executables
executionengine
Expand Down Expand Up @@ -233,6 +234,7 @@ https
HWND
Hyperlink
IAppx
ICheckpoint
IConfiguration
icu
IDX
Expand Down Expand Up @@ -293,6 +295,7 @@ LONGLONG
LPCGUID
LPCSTR
LPVOID
Luid
mailto
MAJORVERSION
makeappx
Expand Down Expand Up @@ -466,6 +469,7 @@ resetpins
resheader
resmimetype
RESOLVESOURCE
RESTARTAPPS
RESTSOURCE
resw
resx
Expand Down Expand Up @@ -508,6 +512,7 @@ SHELLEXECUTEINFOA
SHELLEXECUTEINFOW
shlobj
Shlwapi
SHTDN
shtypes
signtool
silentwithprogress
Expand Down
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ minexample
minidump
minschema
missingdependency
mkgmtime
MMmmbbbb
mof
monicka
Expand Down
11 changes: 11 additions & 0 deletions doc/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,15 @@ You can enable the feature as shown below.
"experimentalFeatures": {
"windowsFeature": true
},
```

### reboot

This feature enables support for initiating a reboot.
You can enable the feature as shown below.

```json
"experimentalFeatures": {
"reboot": true
},
```
5 changes: 5 additions & 0 deletions schemas/JSON/settings/settings.schema.0.2.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@
"description": "Enable support for enabling Windows Feature(s)",
"type": "boolean",
"default": false
},
"reboot": {
"description": "Enable support for initiating a reboot",
"type": "boolean",
"default": false
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/AppInstallerCLICore/AppInstallerCLICore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@
<ItemGroup>
<ClInclude Include="Argument.h" />
<ClInclude Include="ChannelStreams.h" />
<ClInclude Include="CheckpointManager.h" />
<ClInclude Include="Command.h" />
<ClInclude Include="Commands\COMCommand.h" />
<ClInclude Include="Commands\CompleteCommand.h" />
Expand All @@ -371,6 +372,7 @@
<ClInclude Include="Commands\ShowCommand.h" />
<ClInclude Include="Commands\InstallCommand.h" />
<ClInclude Include="Commands\RootCommand.h" />
<ClInclude Include="Commands\ResumeCommand.h" />
<ClInclude Include="Commands\SourceCommand.h" />
<ClInclude Include="Commands\TestCommand.h" />
<ClInclude Include="Commands\UninstallCommand.h" />
Expand Down Expand Up @@ -414,6 +416,7 @@
<ClInclude Include="Workflows\ShellExecuteInstallerHandler.h" />
<ClInclude Include="Workflows\InstallFlow.h" />
<ClInclude Include="Workflows\ManifestComparator.h" />
<ClInclude Include="Workflows\ResumeFlow.h" />
<ClInclude Include="Workflows\ShowFlow.h" />
<ClInclude Include="Workflows\SourceFlow.h" />
<ClInclude Include="Workflows\UninstallFlow.h" />
Expand All @@ -422,6 +425,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="COMContext.cpp" />
<ClCompile Include="CheckpointManager.cpp" />
<ClCompile Include="Commands\COMCommand.cpp" />
<ClCompile Include="Commands\ConfigureCommand.cpp" />
<ClCompile Include="Commands\ConfigureShowCommand.cpp" />
Expand Down Expand Up @@ -453,6 +457,7 @@
<ClCompile Include="Commands\ShowCommand.cpp" />
<ClCompile Include="Commands\InstallCommand.cpp" />
<ClCompile Include="Commands\RootCommand.cpp" />
<ClCompile Include="Commands\ResumeCommand.cpp" />
<ClCompile Include="Commands\SourceCommand.cpp" />
<ClCompile Include="Commands\UninstallCommand.cpp" />
<ClCompile Include="Commands\UpgradeCommand.cpp" />
Expand Down Expand Up @@ -484,6 +489,7 @@
<ClCompile Include="Workflows\ShellExecuteInstallerHandler.cpp" />
<ClCompile Include="Workflows\InstallFlow.cpp" />
<ClCompile Include="Workflows\ManifestComparator.cpp" />
<ClCompile Include="Workflows\ResumeFlow.cpp" />
<ClCompile Include="Workflows\ShowFlow.cpp" />
<ClCompile Include="Workflows\SourceFlow.cpp" />
<ClCompile Include="Workflows\UninstallFlow.cpp" />
Expand Down
22 changes: 20 additions & 2 deletions src/AppInstallerCLICore/AppInstallerCLICore.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
<ClInclude Include="Commands\ErrorCommand.h">
<Filter>Commands</Filter>
</ClInclude>
<ClInclude Include="Commands\ResumeCommand.h">
<Filter>Commands</Filter>
</ClInclude>
<ClInclude Include="Workflows\ResumeFlow.h">
<Filter>Workflows</Filter>
</ClInclude>
<ClInclude Include="CheckpointManager.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
Expand Down Expand Up @@ -424,10 +433,19 @@
<ClCompile Include="Commands\TestCommand.cpp">
<Filter>Commands</Filter>
</ClCompile>
<ClCompile Include="Commands\DownloadCommand.cpp">
<ClCompile Include="ConfigurationCommon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ConfigurationCommon.cpp">
<ClInclude Include="Commands\DownloadCommand.cpp">
<Filter>Commands</Filter>
</ClInclude>
<ClCompile Include="Commands\ResumeCommand.cpp">
<Filter>Commands</Filter>
</ClCompile>
<ClCompile Include="Workflows\ResumeFlow.cpp">
<Filter>Workflows</Filter>
</ClCompile>
<ClCompile Include="CheckpointManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Commands\ErrorCommand.cpp">
Expand Down
10 changes: 10 additions & 0 deletions src/AppInstallerCLICore/Argument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ namespace AppInstaller::CLI
return { type, "no-upgrade"_liv, ArgTypeCategory::CopyFlagToSubContext };
case Execution::Args::Type::SkipDependencies:
return { type, "skip-dependencies"_liv, ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };
case Execution::Args::Type::AllowReboot:
return { type, "allow-reboot"_liv, ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };

// Uninstall behavior
case Execution::Args::Type::Purge:
Expand Down Expand Up @@ -180,6 +182,10 @@ namespace AppInstaller::CLI
case Execution::Args::Type::ErrorInput:
return { type, "input"_liv, ArgTypeCategory::None };

// Resume command
case Execution::Args::Type::ResumeId:
return { type, "resume-id"_liv, 'g', ArgTypeCategory::None };

// Configuration commands
case Execution::Args::Type::ConfigurationFile:
return { type, "file"_liv, 'f' };
Expand Down Expand Up @@ -355,6 +361,10 @@ namespace AppInstaller::CLI
return Argument{ type, Resource::String::DownloadDirectoryArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, false };
case Args::Type::InstallerType:
return Argument{ type, Resource::String::InstallerTypeArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, false };
case Args::Type::ResumeId:
return Argument{ type, Resource::String::ResumeIdArgumentDescription, ArgumentType::Standard, true };
case Args::Type::AllowReboot:
return Argument{ type, Resource::String::AllowRebootArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Reboot };
default:
THROW_HR(E_UNEXPECTED);
}
Expand Down
166 changes: 166 additions & 0 deletions src/AppInstallerCLICore/CheckpointManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include "CheckpointManager.h"
#include "Command.h"
#include "ExecutionContextData.h"
#include <AppInstallerRuntime.h>

namespace AppInstaller::Checkpoints
{
using namespace AppInstaller::CLI;
using namespace AppInstaller::Repository::Microsoft;
using namespace AppInstaller::SQLite;

// This checkpoint name is reserved for the starting checkpoint which captures the automatic metadata.
constexpr std::string_view s_AutomaticCheckpoint = "automatic"sv;
constexpr std::string_view s_CheckpointsFileName = "checkpoints.db"sv;

std::filesystem::path CheckpointManager::GetCheckpointDatabasePath(const std::string_view& resumeId, bool createCheckpointDirectory)
{
const auto checkpointsDirectory = Runtime::GetPathTo(Runtime::PathName::CheckpointsLocation) / resumeId;

if (createCheckpointDirectory)
{
if (!std::filesystem::exists(checkpointsDirectory))
{
AICLI_LOG(Repo, Info, << "Creating checkpoint database directory: " << checkpointsDirectory);
std::filesystem::create_directories(checkpointsDirectory);
}
else
{
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_CANNOT_MAKE), !std::filesystem::is_directory(checkpointsDirectory));
}
}

auto recordPath = checkpointsDirectory / s_CheckpointsFileName;
return recordPath;
}

CheckpointManager::CheckpointManager()
{
GUID resumeId;
std::ignore = CoCreateGuid(&resumeId);
m_resumeId = Utility::ConvertGuidToString(resumeId);
const auto& checkpointDatabasePath = GetCheckpointDatabasePath(m_resumeId, true);
m_checkpointDatabase = CheckpointDatabase::CreateNew(checkpointDatabasePath.u8string());
}

CheckpointManager::CheckpointManager(const std::string& resumeId)
{
m_resumeId = resumeId;
const auto& checkpointDatabasePath = GetCheckpointDatabasePath(m_resumeId);
m_checkpointDatabase = CheckpointDatabase::Open(checkpointDatabasePath.u8string());
}

void CheckpointManager::CreateAutomaticCheckpoint(CLI::Execution::Context& context)
{
CheckpointDatabase::IdType startCheckpointId = m_checkpointDatabase->AddCheckpoint(s_AutomaticCheckpoint);
Checkpoint<AutomaticCheckpointData> automaticCheckpoint{ m_checkpointDatabase, startCheckpointId };

automaticCheckpoint.Set(AutomaticCheckpointData::ClientVersion, {}, AppInstaller::Runtime::GetClientVersion());

const auto& executingCommand = context.GetExecutingCommand();
if (executingCommand != nullptr)
{
automaticCheckpoint.Set(AutomaticCheckpointData::Command, {}, std::string{ executingCommand->FullName() });
}

const auto& argTypes = context.Args.GetTypes();
for (auto type : argTypes)
{
const auto& argument = std::to_string(static_cast<int>(type));
auto argumentType = Argument::ForType(type).Type();

if (argumentType == ArgumentType::Flag)
{
automaticCheckpoint.Set(AutomaticCheckpointData::Arguments, argument, {});
}
else
{
const auto& values = *context.Args.GetArgs(type);
automaticCheckpoint.SetMany(AutomaticCheckpointData::Arguments, argument, values);
}
}
}

void LoadCommandArgsFromAutomaticCheckpoint(CLI::Execution::Context& context, Checkpoint<AutomaticCheckpointData>& automaticCheckpoint)
{
for (const auto& fieldName : automaticCheckpoint.GetFieldNames(AutomaticCheckpointData::Arguments))
{
// Command arguments are represented as integer strings in the checkpoint record.
Execution::Args::Type type = static_cast<Execution::Args::Type>(std::stoi(fieldName));
auto argumentType = Argument::ForType(type).Type();
if (argumentType == ArgumentType::Flag)
{
context.Args.AddArg(type);
}
else
{
const auto& values = automaticCheckpoint.GetMany(AutomaticCheckpointData::Arguments, fieldName);
for (const auto& value : values)
{
context.Args.AddArg(type, value);
}
}
}
}

std::optional<Checkpoint<AutomaticCheckpointData>> CheckpointManager::GetAutomaticCheckpoint()
{
const auto& checkpointIds = m_checkpointDatabase->GetCheckpointIds();
if (checkpointIds.empty())
{
return {};
}

CheckpointDatabase::IdType automaticCheckpointId = checkpointIds.back();
return Checkpoint<AutomaticCheckpointData>{ m_checkpointDatabase, automaticCheckpointId };
}

Checkpoint<CLI::Execution::Data> CheckpointManager::CreateCheckpoint(std::string_view checkpointName)
{
CheckpointDatabase::IdType checkpointId = m_checkpointDatabase->AddCheckpoint(checkpointName);
Checkpoint<CLI::Execution::Data> checkpoint{ m_checkpointDatabase, checkpointId };
return checkpoint;
}

std::vector<Checkpoint<CLI::Execution::Data>> CheckpointManager::GetCheckpoints()
{
auto checkpointIds = m_checkpointDatabase->GetCheckpointIds();
if (checkpointIds.empty())
{
return {};
}

// Remove the last checkpoint (automatic)
checkpointIds.pop_back();

std::vector<Checkpoint<CLI::Execution::Data>> checkpoints;
for (const auto& checkpointId : checkpointIds)
{
checkpoints.emplace_back(Checkpoint<CLI::Execution::Data>{ m_checkpointDatabase, checkpointId });
}

return checkpoints;
}

void CheckpointManager::CleanUpDatabase()
{
if (m_checkpointDatabase)
{
m_checkpointDatabase.reset();
}

if (!m_resumeId.empty())
{
const auto& checkpointDatabasePath = GetCheckpointDatabasePath(m_resumeId);
if (std::filesystem::exists(checkpointDatabasePath))
{
const auto& checkpointDatabaseParentDirectory = checkpointDatabasePath.parent_path();
AICLI_LOG(CLI, Info, << "Deleting Checkpoint database directory: " << checkpointDatabaseParentDirectory);
std::filesystem::remove_all(checkpointDatabaseParentDirectory);
}
}
}
}
Loading

0 comments on commit de53456

Please sign in to comment.