* Initial template for the AppLifecycle object and it's tests.

* Initial set of components

* Basic Launch and Protocol support

* Move registration methods to new runtimeclass.  Stub out new ancillary interfaces on the event args classes.

* Remove samples from the project dll.

* Remove work for file type associations for now.
Remove shared samples completely.

* Block registration for packaged apps (they should use their manifest for v1).  Make GetActivatedEventArgs defer to the platform for packaged apps.

* Add LaunchActivatedEventArgs test.

* Remove unneeded interfaces.

* use a static const wstring instead of a C define for comparison.

* PR feedback around default constructor.

* PR feedback

* PR feedback

* PR Feedback

* PR Feedback
This commit is contained in:
Scott Darnell 2020-10-30 20:50:59 -07:00 коммит произвёл GitHub
Родитель dfb500dcbd
Коммит b3951a46fb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
32 изменённых файлов: 534 добавлений и 370 удалений

Просмотреть файл

@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dev", "dev", "{448ED2E5-0B37-4D97-9E6B-8C10A507976A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleWinRT", "SampleWinRT", "{428CCA9E-ADC5-4917-B51B-7D13E35950C5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{F3659DFF-232D-46E0-967E-61FCC9A1132F}"
ProjectSection(SolutionItems) = preProject
docs\contributor-guide.md = docs\contributor-guide.md
@ -15,12 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{F3659DFF-2
docs\roadmap.md = docs\roadmap.md
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleWinRT", "dev\SampleWinRT\SampleWinRT.vcxitems", "{0DE4FEFE-5471-4B50-B74B-D817A02B7F0D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleFlatC", "SampleFlatC", "{8A5C2FE6-86D7-4AAA-BE2E-924B8E03B888}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleFlatC", "dev\SampleFlatC\SampleFlatC.vcxitems", "{CDCE22EC-F7BF-43D4-95D8-2E786229A4E5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8630F7AA-2969-4DC9-8700-9B468C1DC21D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppShared", "test\CppShared\CppShared.vcxitems", "{682DED8C-3A27-48CD-866D-E853EA2024DE}"
@ -31,15 +23,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppTest_Win32", "test\CppTe
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppTest_UWP", "test\CppTest_UWP\CppTest_UWP.vcxproj", "{B1A6F5EC-5418-4354-BACF-F7D998EE960D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AppLifecycle", "AppLifecycle", "{3DE93B2F-F887-437D-B512-6B1024ABA290}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppLifecycle", "dev\AppLifecycle\AppLifecycle.vcxitems", "{E3A522A3-6635-4A42-BDED-1AF46A15F63C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppLifecycle", "test\AppLifecycle\AppLifecycle.vcxitems", "{80E07022-9E99-44FE-B875-901FB6C82F52}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
dev\SampleWinRT\SampleWinRT.vcxitems*{0de4fefe-5471-4b50-b74b-d817a02b7f0d}*SharedItemsImports = 9
test\CppShared\CppShared.vcxitems*{682ded8c-3a27-48cd-866d-e853ea2024de}*SharedItemsImports = 9
test\AppLifecycle\AppLifecycle.vcxitems*{80e07022-9e99-44fe-b875-901fb6c82f52}*SharedItemsImports = 9
test\CppShared\CppShared.vcxitems*{b1a6f5ec-5418-4354-bacf-f7d998ee960d}*SharedItemsImports = 4
dev\SampleFlatC\SampleFlatC.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4
dev\SampleWinRT\SampleWinRT.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4
test\CppShared\CppShared.vcxitems*{c62688a1-16a0-4729-b6ed-842f4faa29f3}*SharedItemsImports = 4
dev\SampleFlatC\SampleFlatC.vcxitems*{cdce22ec-f7bf-43d4-95d8-2e786229a4e5}*SharedItemsImports = 9
dev\AppLifecycle\AppLifecycle.vcxitems*{e3a522a3-6635-4a42-bded-1af46a15f63c}*SharedItemsImports = 9
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_test|Any CPU = Debug_test|Any CPU
@ -157,14 +153,13 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{428CCA9E-ADC5-4917-B51B-7D13E35950C5} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A}
{0DE4FEFE-5471-4B50-B74B-D817A02B7F0D} = {428CCA9E-ADC5-4917-B51B-7D13E35950C5}
{8A5C2FE6-86D7-4AAA-BE2E-924B8E03B888} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A}
{CDCE22EC-F7BF-43D4-95D8-2E786229A4E5} = {8A5C2FE6-86D7-4AAA-BE2E-924B8E03B888}
{682DED8C-3A27-48CD-866D-E853EA2024DE} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A}
{C62688A1-16A0-4729-B6ED-842F4FAA29F3} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{B1A6F5EC-5418-4354-BACF-F7D998EE960D} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{3DE93B2F-F887-437D-B512-6B1024ABA290} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A}
{E3A522A3-6635-4A42-BDED-1AF46A15F63C} = {3DE93B2F-F887-437D-B512-6B1024ABA290}
{80E07022-9E99-44FE-B875-901FB6C82F52} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77}

Просмотреть файл

@ -33,7 +33,6 @@ function PublishFile {
PublishFile -IfExists $FullBuildOutput\projectreunion_dll\Microsoft.ProjectReunion.dll $FullPublishDir\Microsoft.ProjectReunion\
PublishFile -IfExists $FullBuildOutput\projectreunion_dll\Microsoft.ProjectReunion.lib $FullPublishDir\Microsoft.ProjectReunion\
PublishFile -IfExists $FullBuildOutput\projectreunion_dll\SampleFlatC.h $FullPublishDir\Microsoft.ProjectReunion\
#PublishFile -IfExists $FullBuildOutput\projectreunion_dll\Microsoft.ProjectReunion.pri $FullPublishDir\Microsoft.ProjectReunion\
#UNDONE - xaml vcxproj re-runs an mdmerge into the sdk node, we are skipping this for now and leaving the winmd in its normal outdir
#PublishFile -IfExists $FullBuildOutput\projectreunion_dll\sdk\Microsoft.ProjectReunion.winmd $FullPublishDir\Microsoft.ProjectReunion\sdk\

Просмотреть файл

@ -25,7 +25,6 @@
<file target="lib\uap10.0" src="Intellisense\Microsoft.ProjectReunion.xml"/>
<!-- C++ projects need the flat C header declarations and implib -->
<file target="lib\native" src="$BUILDOUTPUT$\$BUILDFLAVOR$\$BUILDARCH$\Microsoft.ProjectReunion\Microsoft.ProjectReunion.lib" />
<file target="include" src="$BUILDOUTPUT$\$BUILDFLAVOR$\$BUILDARCH$\Microsoft.ProjectReunion\SampleFlatC.h" />
<!-- <file target="tools" src="$TOOLSDIR$\**\*.*"/> -->

Просмотреть файл

@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
namespace winrt::Microsoft::ProjectReunion::implementation
{
using namespace winrt::Windows::ApplicationModel::Activation;
class ActivatedEventArgsBase : public winrt::implements<ActivatedEventArgsBase,
IActivatedEventArgs>
{
public:
// IActivatedEventArgs
ActivationKind Kind()
{
return m_kind;
}
ApplicationExecutionState PreviousExecutionState()
{
return m_previousState;
}
SplashScreen SplashScreen()
{
return m_splashScreen;
}
protected:
ActivatedEventArgsBase() = default;
ActivationKind m_kind = ActivationKind::Launch;
ApplicationExecutionState m_previousState;
winrt::Windows::ApplicationModel::Activation::SplashScreen m_splashScreen{ nullptr };
};
}

Просмотреть файл

@ -0,0 +1,76 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include <pch.h>
#include <ActivationRegistrationManager.h>
#include <ActivationRegistrationManager.g.cpp>
#include "LaunchActivatedEventArgs.h"
#include "ProtocolActivatedEventArgs.h"
#include "Shared.h"
namespace winrt::Microsoft::ProjectReunion::implementation
{
void ActivationRegistrationManager::RegisterForFileTypeActivation(hstring const& groupName,
hstring const& logo, array_view<hstring const> supportedFileTypes,
array_view<hstring const> supportedVerbs)
{
throw hresult_not_implemented();
}
void ActivationRegistrationManager::RegisterForProtocolActivation(hstring const& scheme,
hstring const& displayName)
{
if (scheme.empty() || displayName.empty())
{
throw winrt::hresult_invalid_argument();
}
if (HasIdentity())
{
throw hresult_not_implemented();
}
RegisterProtocol(scheme.c_str(), displayName.c_str());
}
void ActivationRegistrationManager::RegisterForStartupActivation(hstring const& taskId,
bool isEnabled, hstring const& displayName)
{
throw hresult_not_implemented();
}
void ActivationRegistrationManager::RegisterForToastActivation(hstring const& displayName)
{
throw hresult_not_implemented();
}
void ActivationRegistrationManager::UnregisterForFileTypeActivation(hstring const& groupName)
{
throw hresult_not_implemented();
}
void ActivationRegistrationManager::UnregisterForProtocolActivation(hstring const& scheme)
{
if (scheme.empty())
{
throw winrt::hresult_invalid_argument();
}
if (HasIdentity())
{
throw hresult_not_implemented();
}
UnregisterProtocol(scheme.c_str());
}
void ActivationRegistrationManager::UnregisterForStartupActivation()
{
throw hresult_not_implemented();
}
void ActivationRegistrationManager::UnregisterForToastActivation()
{
throw hresult_not_implemented();
}
}

Просмотреть файл

@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include <ActivationRegistrationManager.g.h>
namespace winrt::Microsoft::ProjectReunion::implementation
{
struct ActivationRegistrationManager
{
ActivationRegistrationManager() = default;
static void RegisterForFileTypeActivation(hstring const& groupName, hstring const& logo,
array_view<hstring const> supportedFileTypes, array_view<hstring const> supportedVerbs);
static void RegisterForProtocolActivation(hstring const& scheme, hstring const& displayName);
static void RegisterForStartupActivation(hstring const& taskId, bool isEnabled,
hstring const& displayName);
static void RegisterForToastActivation(hstring const& displayName);
static void UnregisterForFileTypeActivation(hstring const& groupName);
static void UnregisterForProtocolActivation(hstring const& scheme);
static void UnregisterForStartupActivation();
static void UnregisterForToastActivation();
};
}
namespace winrt::Microsoft::ProjectReunion::factory_implementation
{
struct ActivationRegistrationManager : ActivationRegistrationManagerT<ActivationRegistrationManager,
implementation::ActivationRegistrationManager>
{
};
}

Просмотреть файл

@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include <pch.h>
#include <AppLifecycle.h>
#include <AppLifecycle.g.cpp>
#include "LaunchActivatedEventArgs.h"
#include "ProtocolActivatedEventArgs.h"
#include "Shared.h"
namespace winrt::Microsoft::ProjectReunion::implementation
{
std::tuple<std::wstring, std::wstring> ParseCommandLine(std::wstring commandLine)
{
auto argsStart = commandLine.rfind(L"----") + 4;
if (argsStart == std::wstring::npos)
{
return {L"", L""};
}
// We explicitly use find_first_of here, so that the resulting data may contain : as a valid character.
auto argsEnd = commandLine.find_first_of(L":", argsStart);
if (argsEnd == std::wstring::npos)
{
return {L"", L""};
}
if (argsStart > argsEnd)
{
throw std::overflow_error("commandLine");
}
auto argsLength = argsEnd - argsStart;
auto dataStart = argsEnd + 1;
return {commandLine.substr(argsStart, argsLength), commandLine.substr(dataStart)};
}
Windows::ApplicationModel::Activation::IActivatedEventArgs AppLifecycle::GetActivatedEventArgs()
{
if (HasIdentity())
{
return Windows::ApplicationModel::AppInstance::GetActivatedEventArgs();
}
else
{
// Generate IActivatedEventArgs for non-Packaged applications.
std::wstring contractId;
std::wstring contractData;
auto commandLine = std::wstring(GetCommandLine());
std::tie(contractId, contractData) = ParseCommandLine(commandLine);
if (!contractId.empty() && contractId == c_protocolArgumentString)
{
return winrt::make<ProtocolActivatedEventArgs>(contractData);
}
return winrt::make<LaunchActivatedEventArgs>(commandLine);
}
}
}

Просмотреть файл

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include <AppLifecycle.g.h>
namespace winrt::Microsoft::ProjectReunion::implementation
{
struct AppLifecycle
{
AppLifecycle() = default;
static Windows::ApplicationModel::Activation::IActivatedEventArgs GetActivatedEventArgs();
};
}
namespace winrt::Microsoft::ProjectReunion::factory_implementation
{
struct AppLifecycle : AppLifecycleT<AppLifecycle, implementation::AppLifecycle>
{
};
}

Просмотреть файл

@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
namespace Microsoft.ProjectReunion
{
static runtimeclass AppLifecycle
{
static Windows.ApplicationModel.Activation.IActivatedEventArgs GetActivatedEventArgs();
}
static runtimeclass ActivationRegistrationManager
{
static void RegisterForFileTypeActivation(String groupName, String logo, String[] supportedFileTypes, String[] supportedVerbs);
static void RegisterForProtocolActivation(String scheme, String displayName);
static void RegisterForStartupActivation(String taskId, Boolean isEnabled, String displayName);
static void RegisterForToastActivation(String displayName);
static void UnregisterForFileTypeActivation(String groupName);
static void UnregisterForProtocolActivation(String scheme);
static void UnregisterForStartupActivation();
static void UnregisterForToastActivation();
};
}

Просмотреть файл

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<ItemsProjectGuid>{E3A522A3-6635-4A42-BDED-1AF46A15F63C}</ItemsProjectGuid>
<ItemsProjectName>AppLifecycle</ItemsProjectName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectCapability Include="SourceItemsFromImports" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)ActivationRegistrationManager.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Shared.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)ActivatedEventArgsBase.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ActivationRegistrationManager.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Shared.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)LaunchActivatedEventArgs.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ProtocolActivatedEventArgs.h" />
<Midl Include="$(MSBuildThisFileDirectory)AppLifecycle.idl" />
<ClInclude Include="$(MSBuildThisFileDirectory)AppLifecycle.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)AppLifecycle.cpp" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include "ActivatedEventArgsBase.h"
namespace winrt::Microsoft::ProjectReunion::implementation
{
using namespace winrt::Windows::ApplicationModel::Activation;
class LaunchActivatedEventArgs : public winrt::implements<LaunchActivatedEventArgs,
ActivatedEventArgsBase, ILaunchActivatedEventArgs>
{
public:
LaunchActivatedEventArgs(const std::wstring& args) :
m_args(args)
{
m_kind = ActivationKind::Launch;
}
// ILaunchActivatedEventArgs
winrt::hstring Arguments()
{
return m_args.c_str();
}
winrt::hstring TileId()
{
// This implementation is only used for Win32 which don't support secondary tiles.
return L"";
}
private:
std::wstring m_args;
};
}

Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include <winrt/Windows.Foundation.h>
#include "ActivatedEventArgsBase.h"
namespace winrt::Microsoft::ProjectReunion::implementation
{
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::ApplicationModel::Activation;
class ProtocolActivatedEventArgs : public winrt::implements<ProtocolActivatedEventArgs,
ActivatedEventArgsBase, IProtocolActivatedEventArgs>
{
public:
ProtocolActivatedEventArgs(const std::wstring& uri) : m_uri(winrt::Windows::Foundation::Uri(uri))
{
m_kind = ActivationKind::Protocol;
}
// IProtocolActivatedEventArgs
winrt::Windows::Foundation::Uri Uri()
{
return m_uri;
}
private:
winrt::Windows::Foundation::Uri m_uri{nullptr};
};
}

101
dev/AppLifecycle/Shared.cpp Normal file
Просмотреть файл

@ -0,0 +1,101 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include <pch.h>
#include "Shared.h"
namespace winrt::Microsoft::ProjectReunion::implementation
{
std::wstring GetFullIdentityString()
{
std::wstring identityString;
WCHAR idNameBuffer[PACKAGE_FULL_NAME_MAX_LENGTH+1];
UINT32 idNameBufferLen = ARRAYSIZE(idNameBuffer);
if (::GetCurrentPackageFullName(&idNameBufferLen, idNameBuffer) == ERROR_SUCCESS)
{
identityString = idNameBuffer;
}
return identityString;
}
bool HasIdentity()
{
return !(GetFullIdentityString()).empty();
}
std::wstring GetModulePath()
{
std::wstring path(100, L'?');
uint32_t path_size{};
DWORD actual_size{};
do
{
path_size = static_cast<uint32_t>(path.size());
actual_size = ::GetModuleFileName(nullptr, path.data(), path_size);
if (actual_size + 1 > path_size)
{
path.resize(path_size * 2, L'?');
}
} while (actual_size + 1 > path_size);
path.resize(actual_size);
return path;
}
std::wstring CreateAssocKeyPath(PCWSTR assocName)
{
std::wstring path{ LR"(SOFTWARE\Classes\)" };
path += assocName;
return path;
}
void RegisterProtocol(PCWSTR scheme, PCWSTR displayName, _In_opt_ const GUID* delegateExecute)
{
std::wstring key_path{ CreateAssocKeyPath(scheme) };
wil::unique_hkey key;
THROW_IF_WIN32_ERROR(::RegCreateKeyEx(HKEY_CURRENT_USER, key_path.c_str(), 0, nullptr, 0,
KEY_WRITE, nullptr, key.put(), nullptr));
std::wstring defaultValue{ L"URL:" };
defaultValue += displayName;
THROW_IF_WIN32_ERROR(::RegSetValueEx(key.get(), nullptr, 0, REG_SZ,
reinterpret_cast<BYTE const*>(defaultValue.c_str()),
static_cast<uint32_t>((defaultValue.size() + 1) * sizeof(wchar_t))));
std::wstring urlProtocolValue{ L"" };
defaultValue += displayName;
THROW_IF_WIN32_ERROR(::RegSetValueEx(key.get(), L"URL Protocol", 0, REG_SZ,
reinterpret_cast<BYTE const*>(urlProtocolValue.c_str()),
static_cast<uint32_t>((urlProtocolValue.size() + 1) * sizeof(wchar_t))));
key_path += LR"(\shell\open\command)";
key.reset();
THROW_IF_WIN32_ERROR(::RegCreateKeyEx(HKEY_CURRENT_USER, key_path.c_str(), 0, nullptr, 0,
KEY_WRITE, nullptr, key.put(), nullptr));
auto command = GetModulePath();
command += L" ----" + c_protocolArgumentString + L":%1";
THROW_IF_WIN32_ERROR(::RegSetValueEx(key.get(), nullptr, 0, REG_SZ,
reinterpret_cast<BYTE const*>(command.c_str()),
static_cast<uint32_t>((command.size() + 1) * sizeof(wchar_t))));
if (delegateExecute)
{
std::wstring delegateClsid{ LR"({????????-????-????-????-????????????})" };
::StringFromGUID2(*delegateExecute, delegateClsid.data(), 39);
THROW_IF_WIN32_ERROR(::RegSetValueEx(key.get(), L"DelegateExecute", 0, REG_SZ,
reinterpret_cast<BYTE const*>(delegateClsid.c_str()),
static_cast<uint32_t>((delegateClsid.size() + 1) * sizeof(wchar_t))));
}
}
void UnregisterProtocol(PCWSTR scheme)
{
std::wstring key_path{ CreateAssocKeyPath(scheme) };
::RegDeleteTree(HKEY_CURRENT_USER, key_path.c_str());
}
}

16
dev/AppLifecycle/Shared.h Normal file
Просмотреть файл

@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
namespace winrt::Microsoft::ProjectReunion::implementation
{
static const std::wstring c_protocolArgumentString = L"ms-protocol"; //L"ms-protocol"
std::wstring GetFullIdentityString();
bool HasIdentity();
std::wstring GetModulePath();
std::wstring CreateAssocKeyPath(PCWSTR assocName);
void RegisterProtocol(PCWSTR scheme, PCWSTR displayName, _In_opt_ const GUID* delegateExecute = nullptr);
void UnregisterProtocol(PCWSTR scheme);
}

Просмотреть файл

@ -1,7 +1,3 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
SampleFlatApiCreate
CloseSampleFlatApi
GetSampleFlatApiString

Просмотреть файл

@ -104,8 +104,7 @@
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
<Import Project="..\SampleFlatC\SampleFlatC.vcxitems" Label="Shared" />
<Import Project="..\SampleWinRT\SampleWinRT.vcxitems" Label="Shared" />
<Import Project="..\AppLifecycle\AppLifecycle.vcxitems" Label="AppLifecycle" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

Просмотреть файл

@ -1,7 +1,10 @@
#pragma once
#include <unknwn.h>
#include <ShObjIdl_core.h>
#include <thread>
#include <mutex>
#include <list>
#include <stdexcept>
#include <wil/cppwinrt.h>
#include <wil/token_helpers.h>
#include <wil/resource.h>
@ -9,4 +12,6 @@
#include <appmodel.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
#include <NotificationActivationCallback.h>

Просмотреть файл

@ -1,59 +0,0 @@
# Adding a new Flat C API Component
This directory is a sample of adding an API with a "flat C" style to Project Reunion.
Flat C APIs define an ABI using C-based headers exported from a DLL. Apps can use the
APIs from an import library or through a projection that applies a wrapper.
## Adding the shared project
1. In Visual Studio, right-click the `dev` node in the Solution and choose "New Solution Folder"
2. Pick a name for your new project (the rest of this example uses `Muffins`)
3. Right-click the `Muffins` solution folder and use "Add > New Project"
4. Use the "Shared Items Project", set the name (`Muffins`)
4. For path use the solution root plus `\\dev` - the final path will be in `\\dev\\Muffins`
## Reference the project
1. Right-click the **ProjectReunion** project, use "Add > Reference"
2. Choose `Muffins` from the list of "Shared" items
## Add public header
1. Right-click the shared project and use "Add > New Item"
2. From the "Installed > Visual C++ > Code" list, select "Header (.h)"
3. Pick a good name (for the rest of this example, we'll use `Muffins` again, so "muffins.h")
5. Define the ABI for the implementation
Follow the example of [SampleFlatC](./SampleFlatC.h):
* Use `STDAPI` and `STDAPI_(type)` to define entrypoints
* Use scoped enumerations (like `enum class`) instead of preprocessor definitions
## Add implementation
1. Add `.cpp` files that implement the APIs in the usual way
2. For code using C++-with-exceptions use an appropriate exception guard
## Publish header
1. In the `.vcxitems` for the new project, manually add something like this, per [SampleFlatC.vcxitems](./SampleFlatC.vcxitems)
```xml
<!-- Include this header in the set being published for use with the DLL -->
<ItemGroup>
<PublicHeaders Include="$(MSBuildThisFileDirectory)SampleFlatC.h"/>
</ItemGroup>
```
## Adding exports
1. In [ProjectReunion.def](../dll/ProjectReunion.def) add the list of exported methods
## Other notes
Be sure to add the copyright and license marker to all source files:
```c++
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
```

Просмотреть файл

@ -1,41 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "SampleFlatC.h"
#include <string>
struct MyRealType
{
std::wstring theString;
};
STDAPI SampleFlatApiCreate(
_In_ LPCWSTR theString,
_Outptr_ HSAMPLEFLATAPI* sampleFlat) try
{
RETURN_HR_IF(E_INVALIDARG, !theString);
auto real = std::make_unique<MyRealType>();
real->theString = theString;
*sampleFlat = reinterpret_cast<HSAMPLEFLATAPI>(real.release());
return S_OK;
}
CATCH_RETURN();
STDAPI_(VOID) CloseSampleFlatApi(HSAMPLEFLATAPI sampleFlat) try
{
auto real = std::unique_ptr<MyRealType>(reinterpret_cast<MyRealType*>(sampleFlat));
// Do something with 'real', the destructor will clean it up
}
CATCH_LOG();
STDAPI GetSampleFlatApiString(
_In_ HSAMPLEFLATAPI sampleFlat,
_Outptr_ LPWSTR* theString) try
{
auto real = reinterpret_cast<MyRealType*>(sampleFlat);
auto cloned = wil::make_cotaskmem_string(real->theString.data());
*theString = cloned.release();
return S_OK;
}
CATCH_RETURN();

Просмотреть файл

@ -1,30 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include <windows.h>
DECLARE_HANDLE(HSAMPLEFLATAPI);
STDAPI SampleFlatApiCreate(
_In_ LPCWSTR theString,
_Outptr_ HSAMPLEFLATAPI* sampleFlat);
STDAPI_(VOID) CloseSampleFlatApi(
HSAMPLEFLATAPI sampleFlat);
STDAPI GetSampleFlatApiString(
_In_ HSAMPLEFLATAPI sampleFlat,
_Outptr_ LPWSTR* theString);
// Include <wil/resource.h> from the NuGet package Microsoft.Windows.ImplementationLibrary
// before this file to have this handy lifecycle helper for C++ light up
#ifdef __WIL_RESOURCE
namespace wil
{
using unique_sampleflat_handle = unique_any<HSAMPLEFLATAPI, decltype(CloseSampleFlatApi), &::CloseSampleFlatApi>;
}
#endif

Просмотреть файл

@ -1,52 +0,0 @@
# Adding a new WinRT Component
This directory is a sample of adding a WinRT component to Project Reunion.
WinRT-based APIs are defined using [MIDL3](https://docs.microsoft.com/en-us/uwp/midl-3/)
and typically [implemented with C++/WinRT](https://github.com/Microsoft/cppwinrt). It's
straightforward to add a new component in this manner.
## Adding the shared project
1. In Visual Studio, right-click the `dev` node in the Solution and choose "New Solution Folder"
2. Pick a name for your new project (the rest of this example uses `Muffins`)
3. Right-click the `Muffins` solution folder and use "Add > New Project"
4. Use the "Shared Items Project", set the name (`Muffins`)
4. For path use the solution root plus `\\dev` - the final path will be in `\\dev\\Muffins`
## Reference the project
1. Right-click the **ProjectReunion** project, use "Add > Reference"
2. Choose `Muffins` from the list of "Shared" items
## Add IDL and implementation
1. Right-click the shared project and use "Add > New Item"
2. From the Installed > Visual C++ > Code list, select "Midl File (.idl)"
3. Pick a good name (for the rest of this example, we'll use `Muffins` again, so "muffins.idl")
4. Remove the default `import ...` statements that visual studio generates
Follow the example of [SampleWinRT](./SampleWinRT.idl):
* Use `Microsoft.Muffins` as the namespace
* Add types and classes as necessary
Add a header and `.cpp` file and an implementation.
Be sure to add the copyright and license marker to all source files:
```c++
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
```
Add any C++/WinRT projected headers used by the implementation to
the [pch.h](../ProjectReunion_DLL/pch.h) to reduce compilation times.
## Testing
1. Add a new file to the [CppShared](../../test/CppShared/CppShared.vcxitems)
2. Follow the existing pattern of adding a `TEST_CLASS` with `TEST_METHOD` for facets of your implementation
3. Build the project and use the Visual Studio Test Explorer to run all tests
For very large surfaces with lots of tests, add a new directory under `test`
with its own shared items project.

Просмотреть файл

@ -1,6 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include <pch.h>
#include <SampleWinRT.h>
#include <Common.g.cpp>

Просмотреть файл

@ -1,54 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include <Common.g.h>
namespace winrt::Microsoft::ProjectReunion::implementation
{
struct Common
{
Common() = default;
static void Initialize()
{
}
static hstring AppIdentity()
{
static winrt::hstring fullName = GetFullIdentityString();
return fullName;
}
static bool IsAppContainer()
{
static bool isAppContainer = wil::get_token_is_app_container();
return isAppContainer;
}
static bool HasIdentity()
{
return !AppIdentity().empty();
}
static winrt::hstring GetFullIdentityString()
{
winrt::hstring identityString;
WCHAR idNameBuffer[PACKAGE_FULL_NAME_MAX_LENGTH];
UINT32 idNameBufferLen = ARRAYSIZE(idNameBuffer);
if (::GetCurrentPackageFullName(&idNameBufferLen, idNameBuffer) == ERROR_SUCCESS)
{
identityString = idNameBuffer;
}
return identityString;
}
};
}
namespace winrt::Microsoft::ProjectReunion::factory_implementation
{
struct Common : CommonT<Common, implementation::Common>
{
};
}

Просмотреть файл

@ -1,15 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
namespace Microsoft.ProjectReunion
{
static runtimeclass Common
{
static void Initialize();
static String AppIdentity { get; };
static Boolean IsAppContainer{ get; };
static Boolean HasIdentity{ get; };
};
}

Просмотреть файл

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<ItemsProjectGuid>{0de4fefe-5471-4b50-b74b-d817a02b7f0d}</ItemsProjectGuid>
<ItemsProjectName>SampleWinRT</ItemsProjectName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectCapability Include="SourceItemsFromImports" />
</ItemGroup>
<ItemGroup>
<Midl Include="$(MSBuildThisFileDirectory)SampleWinRT.idl" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)SampleWinRT.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)SampleWinRT.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)README.md" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
using namespace winrt::Windows::ApplicationModel;
using namespace winrt::Windows::ApplicationModel::Activation;
using namespace winrt::Microsoft::ProjectReunion;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace ProjectReunionCppTest
{
TEST_CLASS(AppLifecycleApiTests)
{
#if PRTEST_MODE_UWP
// UWP currently is not supported by these tests.
TEST_METHOD(GetActivatedEventArgsIsNull)
{
Assert::IsTrue(winrt::Microsoft::ProjectReunion::AppLifecycle::GetActivatedEventArgs() == nullptr);
}
#else
TEST_METHOD(GetActivatedEventArgsIsNotNull)
{
Assert::IsTrue(winrt::Microsoft::ProjectReunion::AppLifecycle::GetActivatedEventArgs() != nullptr);
}
TEST_METHOD(GetActivatedEventArgsForLaunch)
{
auto args = winrt::Microsoft::ProjectReunion::AppLifecycle::GetActivatedEventArgs();
Assert::IsTrue(args != nullptr);
Assert::IsTrue(args.Kind() == ActivationKind::Launch);
auto launchArgs = args.as<LaunchActivatedEventArgs>();
Assert::IsTrue(launchArgs != nullptr);
}
#endif
};
}

Просмотреть файл

@ -3,7 +3,7 @@
<PropertyGroup Label="Globals">
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<ItemsProjectGuid>{cdce22ec-f7bf-43d4-95d8-2e786229a4e5}</ItemsProjectGuid>
<ItemsProjectGuid>{80E07022-9E99-44FE-B875-901FB6C82F52}</ItemsProjectGuid>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
@ -14,16 +14,6 @@
<ProjectCapability Include="SourceItemsFromImports" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)SampleFlatC.h"/>
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)README.md" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)SampleFlatC.cpp" />
</ItemGroup>
<ItemGroup>
<PublicHeaders Include="$(MSBuildThisFileDirectory)SampleFlatC.h"/>
<ClCompile Include="$(MSBuildThisFileDirectory)ApiTests.cpp" />
</ItemGroup>
</Project>

Просмотреть файл

@ -7,49 +7,4 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace ProjectReunionCppTest
{
TEST_CLASS(FlatApiTests)
{
public:
TEST_METHOD(Creates)
{
wil::unique_sampleflat_handle temp;
Assert::IsTrue(SUCCEEDED(::SampleFlatApiCreate(L"kittens", &temp)));
Assert::IsTrue(SUCCEEDED(::SampleFlatApiCreate(L"puppies", &temp)));
Assert::IsTrue(FAILED(::SampleFlatApiCreate(nullptr, &temp)));
}
TEST_METHOD(CloseNullOk)
{
CloseSampleFlatApi(nullptr);
}
TEST_METHOD(StringRoundTrip)
{
const wchar_t* tasty = L"muffins";
wil::unique_sampleflat_handle temp;
THROW_IF_FAILED(::SampleFlatApiCreate(tasty, &temp));
wil::unique_cotaskmem_string stored;
Assert::IsTrue(SUCCEEDED(::GetSampleFlatApiString(temp.get(), &stored)));
Assert::IsNotNull(stored.get());
Assert::AreEqual(tasty, stored.get());
}
};
TEST_CLASS(WinRtApiTests)
{
#if PRTEST_MODE_UWP
TEST_METHOD(ContainerTests)
{
Assert::IsTrue(winrt::Microsoft::ProjectReunion::Common::IsAppContainer());
Assert::IsTrue(winrt::Microsoft::ProjectReunion::Common::HasIdentity());
}
#else
TEST_METHOD(ContainerTests)
{
Assert::IsFalse(winrt::Microsoft::ProjectReunion::Common::IsAppContainer());
Assert::IsFalse(winrt::Microsoft::ProjectReunion::Common::HasIdentity());
}
#endif
};
}

Просмотреть файл

@ -111,6 +111,9 @@
<ImportGroup Label="Shared">
<Import Project="..\CppShared\CppShared.vcxitems" Label="Shared" />
</ImportGroup>
<ImportGroup Label="AppLifecycle">
<Import Project="..\AppLifecycle\AppLifecycle.vcxitems" Label="AppLifecycle" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>

Просмотреть файл

@ -10,6 +10,7 @@
#include <wil/resource.h>
#include "CppUnitTest.h"
#include <winrt/Windows.ApplicationModel.Activation.h>
// Test-specific headers, lifted here
#include <SampleFlatC.h>
#include <winrt/Microsoft.ProjectReunion.h>

Просмотреть файл

@ -75,6 +75,9 @@
<ImportGroup Label="Shared">
<Import Project="..\CppShared\CppShared.vcxitems" Label="Shared" />
</ImportGroup>
<ImportGroup Label="AppLifecycle">
<Import Project="..\AppLifecycle\AppLifecycle.vcxitems" Label="AppLifecycle" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>

Просмотреть файл

@ -19,6 +19,7 @@
#include <winrt/Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore.h>
#include <CppUnitTest.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
// Test-specific headers, lifted here
#include <SampleFlatC.h>
#include <winrt/Microsoft.ProjectReunion.h>