* Working on generateprogid

* Added method to generate prog id

* Placeholder changes

* GenerateProgId now works

* Generate handler name

* Write keys for autoPlayContent

* Method signature changes

* Get packagedirectory path

* Parse Desktop Appx content and device elements

* Write registry keys

* Changes while running code

* Tested changes and changes to certain keys

* Addressed certain PR comments

* Implement executeForRemoveRequest

* Replace macros with definition

* Remove usage of widestring.cpp

* return hresult from ntstatus

* Add AutoPlay to remove handlers

* Updated test package with autoPlayHandler extension

* Removed usage of byte buffer

* Corrected indentation

* Spaces and remove copyright line

* Removed comment
This commit is contained in:
jyvenugo 2019-08-09 15:30:33 -07:00 коммит произвёл GitHub
Родитель ab322965d6
Коммит 65c2322b4e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 1351 добавлений и 6 удалений

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

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3c09888b086af669f4a334324b698fe51f4457f551183133d49c3136306ff785
size 3111880
oid sha256:bc838717529809a5ac5eefed213205b89e7c51b1ae03cdb0b23670c87c24888a
size 3112115

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

@ -0,0 +1,617 @@
#include <windows.h>
#include <shlobj_core.h>
#include <CommCtrl.h>
#include <iostream>
#include <algorithm>
#include "RegistryKey.hpp"
#include "AutoPlay.hpp"
#include "GeneralUtil.hpp"
#include <TraceLoggingProvider.h>
#include "MsixTraceLoggingProvider.hpp"
#include "Constants.hpp"
#include "CryptoProvider.hpp"
#include "Base32Encoding.hpp"
#include <StrSafe.h>
using namespace MsixCoreLib;
const PCWSTR AutoPlay::HandlerName = L"AutoPlay";
HRESULT AutoPlay::ExecuteForAddRequest()
{
for (auto autoPlay = m_autoPlay.begin(); autoPlay != m_autoPlay.end(); ++autoPlay)
{
RETURN_IF_FAILED(ProcessAutoPlayForAdd(*autoPlay));
}
return S_OK;
}
HRESULT AutoPlay::ExecuteForRemoveRequest()
{
for (auto autoPlay = m_autoPlay.begin(); autoPlay != m_autoPlay.end(); ++autoPlay)
{
RETURN_IF_FAILED(ProcessAutoPlayForRemove(*autoPlay));
}
return S_OK;
}
HRESULT AutoPlay::ProcessAutoPlayForRemove(AutoPlayObject& autoPlayObject)
{
RegistryKey explorerKey;
RETURN_IF_FAILED(explorerKey.Open(HKEY_LOCAL_MACHINE, explorerRegKeyName.c_str(), KEY_READ | KEY_WRITE));
RegistryKey handlerRootKey;
HRESULT hrCreateSubKey = explorerKey.CreateSubKey(handlerKeyName.c_str(), KEY_READ | KEY_WRITE, &handlerRootKey);
if (SUCCEEDED(hrCreateSubKey))
{
const HRESULT hrDeleteSubKeyTree = handlerRootKey.DeleteTree(autoPlayObject.generatedhandlerName.c_str());
if (FAILED(hrDeleteSubKeyTree) && hrDeleteSubKeyTree != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Unable to delete autoplay generatedHandlerName",
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
TraceLoggingValue(hrDeleteSubKeyTree, "HR"),
TraceLoggingValue(autoPlayObject.generatedhandlerName.c_str(), "GeneratedHandlerName"),
TraceLoggingValue(m_msixRequest->GetPackageFullName(), "PackageFullName "));
}
}
else
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Unable to delete autoplay reg key",
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
TraceLoggingValue(hrCreateSubKey, "HR"),
TraceLoggingValue(autoPlayObject.generatedhandlerName.c_str(), "GeneratedHandlerName"),
TraceLoggingValue(m_msixRequest->GetPackageFullName(), "PackageFullName "));
}
if (autoPlayObject.autoPlayType == DesktopAppxContent)
{
RegistryKey classesRootKey;
HRESULT hrCreateSubKey = classesRootKey.Open(HKEY_LOCAL_MACHINE, classesKeyPath.c_str(), KEY_READ | KEY_WRITE | WRITE_DAC);
if (SUCCEEDED(hrCreateSubKey))
{
const HRESULT hrDeleteSubKeyTree = classesRootKey.DeleteTree(autoPlayObject.generatedProgId.c_str());
if (FAILED(hrDeleteSubKeyTree) && hrDeleteSubKeyTree != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Unable to delete autoplay progId reg key",
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
TraceLoggingValue(hrDeleteSubKeyTree, "HR"),
TraceLoggingValue(autoPlayObject.generatedProgId.c_str(), "GeneratedProgId"),
TraceLoggingValue(m_msixRequest->GetPackageFullName(), "PackageFullName "));
}
}
}
RegistryKey handleEventRootKey;
hrCreateSubKey = explorerKey.CreateSubKey(eventHandlerRootRegKeyName.c_str(), KEY_READ | KEY_WRITE, &handleEventRootKey);
if (SUCCEEDED(hrCreateSubKey))
{
RegistryKey handleEventKey;
HRESULT hrCreateHandleSubKey = handleEventRootKey.CreateSubKey(autoPlayObject.handleEvent.c_str(), KEY_READ | KEY_WRITE, &handleEventKey);
if (SUCCEEDED(hrCreateHandleSubKey))
{
const HRESULT hrDeleteValue = handleEventKey.DeleteValue(autoPlayObject.generatedhandlerName.c_str());
if (FAILED(hrDeleteValue) && hrDeleteValue != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Unable to delete autoplay handleEventKey generatedHandlerName reg key",
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
TraceLoggingValue(hrDeleteValue, "HR"),
TraceLoggingValue(autoPlayObject.generatedhandlerName.c_str(), "GeneratedHandlerName"),
TraceLoggingValue(m_msixRequest->GetPackageFullName(), "PackageFullName "));
return hrDeleteValue;
}
}
else
{
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Unable to delete autoplay reg key",
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
TraceLoggingValue(hrCreateHandleSubKey, "HR"),
TraceLoggingValue(autoPlayObject.generatedhandlerName.c_str(), "GeneratedHandlerName"),
TraceLoggingValue(m_msixRequest->GetPackageFullName(), "PackageFullName "));
return hrCreateHandleSubKey;
}
}
else
{
// Log failure of creating the handleEventRootKey
TraceLoggingWrite(g_MsixTraceLoggingProvider,
"Unable to delete autoplay reg key",
TraceLoggingLevel(WINEVENT_LEVEL_WARNING),
TraceLoggingValue(hrCreateSubKey, "HR"),
TraceLoggingValue(autoPlayObject.generatedhandlerName.c_str(), "GeneratedHandlerName"),
TraceLoggingValue(m_msixRequest->GetPackageFullName(), "PackageFullName "));
return hrCreateSubKey;
}
return S_OK;
}
HRESULT AutoPlay::ParseManifest()
{
ComPtr<IMsixDocumentElement> domElement;
RETURN_IF_FAILED(m_msixRequest->GetPackageInfo()->GetManifestReader()->QueryInterface(UuidOfImpl<IMsixDocumentElement>::iid, reinterpret_cast<void**>(&domElement)));
ComPtr<IMsixElement> element;
RETURN_IF_FAILED(domElement->GetDocumentElement(&element));
ComPtr<IMsixElementEnumerator> extensionEnum;
RETURN_IF_FAILED(element->GetElements(extensionQuery.c_str(), &extensionEnum));
BOOL hasCurrent = FALSE;
RETURN_IF_FAILED(extensionEnum->GetHasCurrent(&hasCurrent));
while (hasCurrent)
{
ComPtr<IMsixElement> extensionElement;
RETURN_IF_FAILED(extensionEnum->GetCurrent(&extensionElement));
Text<wchar_t> extensionCategory;
RETURN_IF_FAILED(extensionElement->GetAttributeValue(categoryAttribute.c_str(), &extensionCategory));
if (wcscmp(extensionCategory.Get(), desktopAppXExtensionCategory.c_str()) == 0)
{
BOOL hc_invokeAction = FALSE;
ComPtr<IMsixElementEnumerator> invokeActionEnum;
RETURN_IF_FAILED(extensionElement->GetElements(invokeActionQuery.c_str(), &invokeActionEnum));
RETURN_IF_FAILED(invokeActionEnum->GetHasCurrent(&hc_invokeAction));
while (hc_invokeAction)
{
ComPtr<IMsixElement> invokeActionElement;
RETURN_IF_FAILED(invokeActionEnum->GetCurrent(&invokeActionElement));
//desktop appx content element
BOOL has_DesktopAppxContent = FALSE;
ComPtr<IMsixElementEnumerator> desktopAppxContentEnum;
RETURN_IF_FAILED(invokeActionElement->GetElements(invokeActionContentQuery.c_str(), &desktopAppxContentEnum));
RETURN_IF_FAILED(desktopAppxContentEnum->GetHasCurrent(&has_DesktopAppxContent));
while (has_DesktopAppxContent)
{
ComPtr<IMsixElement> desktopAppxContentElement;
RETURN_IF_FAILED(desktopAppxContentEnum->GetCurrent(&desktopAppxContentElement));
AutoPlayObject autoPlay;
//autoplay type
autoPlay.autoPlayType = DesktopAppxContent;
//action
Text<wchar_t> action;
RETURN_IF_FAILED(invokeActionElement->GetAttributeValue(actionAttributeName.c_str(), &action));
autoPlay.action = action.Get();
//provider
Text<wchar_t> provider;
RETURN_IF_FAILED(invokeActionElement->GetAttributeValue(providerAttributeName.c_str(), &provider));
autoPlay.provider = provider.Get();
// Get the App's app user model id
autoPlay.appUserModelId = m_msixRequest->GetPackageInfo()->GetId();
//get the logo
autoPlay.defaultIcon = m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath() + m_msixRequest->GetPackageInfo()->GetRelativeLogoPath();
//verb
Text<wchar_t> id;
RETURN_IF_FAILED(desktopAppxContentElement->GetAttributeValue(idAttributeName.c_str(), &id));
autoPlay.id = id.Get();
//content event
Text<wchar_t> handleEvent;
RETURN_IF_FAILED(desktopAppxContentElement->GetAttributeValue(contentEventAttributeName.c_str(), &handleEvent));
autoPlay.handleEvent = handleEvent.Get();
//drop target handler
Text<wchar_t> dropTargetHandler;
RETURN_IF_FAILED(desktopAppxContentElement->GetAttributeValue(dropTargetHandlerAttributeName.c_str(), &dropTargetHandler));
if (dropTargetHandler.Get() != nullptr)
{
autoPlay.dropTargetHandler = dropTargetHandler.Get();
}
//parameters
Text<wchar_t> parameters;
RETURN_IF_FAILED(desktopAppxContentElement->GetAttributeValue(parametersAttributeName.c_str(), &parameters));
if (parameters.Get() != nullptr)
{
autoPlay.parameters = parameters.Get();
}
//GenerateProgId
std::wstring uniqueProgId;
uniqueProgId.append(id.Get());
uniqueProgId.append(handleEvent.Get());
std::wstring generatedProgId;
RETURN_IF_FAILED(GenerateProgId(desktopAppXExtensionCategory.c_str(), uniqueProgId.c_str(), generatedProgId));
autoPlay.generatedProgId = generatedProgId.c_str();
//GenerateHandlerName
std::wstring uniqueHandlerName;
uniqueHandlerName.append(id.Get());
uniqueHandlerName.append(handleEvent.Get());
std::wstring generatedHandlerName;
RETURN_IF_FAILED(GenerateHandlerName(L"DesktopAppXContent", uniqueHandlerName.c_str(), generatedHandlerName));
autoPlay.generatedhandlerName = generatedHandlerName.c_str();
m_autoPlay.push_back(autoPlay);
RETURN_IF_FAILED(desktopAppxContentEnum->MoveNext(&has_DesktopAppxContent));
}
//desktop appx device element
BOOL has_DesktopAppxDevice = FALSE;
ComPtr<IMsixElementEnumerator> desktopAppxDeviceEnum;
RETURN_IF_FAILED(invokeActionElement->GetElements(invokeActionDeviceQuery.c_str(), &desktopAppxDeviceEnum));
RETURN_IF_FAILED(desktopAppxDeviceEnum->GetHasCurrent(&has_DesktopAppxDevice));
while (has_DesktopAppxDevice)
{
ComPtr<IMsixElement> desktopAppxDeviceElement;
RETURN_IF_FAILED(desktopAppxDeviceEnum->GetCurrent(&desktopAppxDeviceElement));
AutoPlayObject autoPlay;
//autoplay type
autoPlay.autoPlayType = DesktopAppxDevice;
//action
Text<wchar_t> action;
RETURN_IF_FAILED(invokeActionElement->GetAttributeValue(actionAttributeName.c_str(), &action));
autoPlay.action = action.Get();
//provider
Text<wchar_t> provider;
RETURN_IF_FAILED(invokeActionElement->GetAttributeValue(providerAttributeName.c_str(), &provider));
autoPlay.provider = provider.Get();
// Get the App's app user model id
autoPlay.appUserModelId = m_msixRequest->GetPackageInfo()->GetId();
//get the logo
autoPlay.defaultIcon = m_msixRequest->GetPackageInfo()->GetPackageDirectoryPath() + m_msixRequest->GetPackageInfo()->GetRelativeLogoPath();
//handle event
Text<wchar_t> handleEvent;
RETURN_IF_FAILED(desktopAppxDeviceElement->GetAttributeValue(deviceEventAttributeName.c_str(), &handleEvent));
autoPlay.handleEvent = handleEvent.Get();
//hwEventHandler
Text<wchar_t> hwEventHandler;
RETURN_IF_FAILED(desktopAppxDeviceElement->GetAttributeValue(hwEventHandlerAttributeName.c_str(), &hwEventHandler));
autoPlay.hwEventHandler = hwEventHandler.Get();
//init cmd line
Text<wchar_t> initCmdLine;
RETURN_IF_FAILED(desktopAppxDeviceElement->GetAttributeValue(InitCmdLineAttributeName.c_str(), &initCmdLine));
if (initCmdLine.Get() != nullptr)
{
autoPlay.initCmdLine = initCmdLine.Get();
}
//GenerateHandlerName
std::wstring uniqueHandlerName;
uniqueHandlerName.append(handleEvent.Get());
std::wstring generatedHandlerName;
RETURN_IF_FAILED(GenerateHandlerName(L"DesktopAppXDevice", uniqueHandlerName.c_str(), generatedHandlerName));
autoPlay.generatedhandlerName = generatedHandlerName.c_str();
m_autoPlay.push_back(autoPlay);
RETURN_IF_FAILED(desktopAppxDeviceEnum->MoveNext(&has_DesktopAppxDevice));
}
RETURN_IF_FAILED(invokeActionEnum->MoveNext(&hc_invokeAction));
}
}
RETURN_IF_FAILED(extensionEnum->MoveNext(&hasCurrent));
}
return S_OK;
}
HRESULT AutoPlay::GenerateProgId(std::wstring categoryName, std::wstring subCategory, std::wstring & generatedProgId)
{
std::wstring packageFamilyName = m_msixRequest->GetPackageInfo()->GetPackageFamilyName();
std::wstring applicationId = m_msixRequest->GetPackageInfo()->GetApplicationId();
if (packageFamilyName.empty() || applicationId.empty() || categoryName.empty())
{
return E_INVALIDARG;
}
// Constants
std::wstring AppXPrefix = L"AppX";
static const size_t MaxProgIDLength = 39;
// The maximum number of characters we can have as base32 encoded is 32.
// We arrive at this due to the interface presented by the GetChars function;
// it is byte only. Ideally, the MaxBase32EncodedStringLength would be
// 35 [39 total for the progID, minus 4 for the prefix]. 35 characters means
// a maximum of 22 bytes in the digest [ceil(35*5/8)]. However, 22 bytes of digest
// actually encodes 36 characters [ceil(22/8*5)]. So we have to reduce the
// character count of the encoded string. At 33 characters, this translates into
// a 21 byte buffer. A 21 byte buffer translates into 34 characters. Although
// this meets the requirements, it is confusing since a 33 character limit
// results in a 34 character long encoding. In comparison, a 32 character long
// encoding divides evenly and always results in a 20 byte digest.
static const size_t MaxBase32EncodedStringLength = 32;
// The maximum number of bytes the digest can be is 20. We arrive at this by:
// - The maximum count of characters [without prefix] in the encoding (32):
// - multiplied by 5 (since each character in base 32 encoding is based off of 5 bits)
// - divided by 8 (to find how many bytes are required)
// - The initial plus 7 is to enable integer math (equivalent of writing ceil)
static const ULONG MaxByteCountOfDigest = (MaxBase32EncodedStringLength * 5 + 7) / 8;
// Build the progIdSeed by appending the incoming strings
// The package family name and the application ID are case sensitive
std::wstring tempProgIDBuilder;
tempProgIDBuilder.append(packageFamilyName);
std::transform(tempProgIDBuilder.begin(), tempProgIDBuilder.end(), tempProgIDBuilder.begin(), ::tolower);
tempProgIDBuilder.append(applicationId);
// The category name and the subcategory are not case sensitive
// so we should lower case them
std::wstring tempLowerBuffer;
tempLowerBuffer.assign(categoryName);
std::transform(tempLowerBuffer.begin(), tempLowerBuffer.end(), tempLowerBuffer.begin(), ::tolower);
tempProgIDBuilder.append(tempLowerBuffer);
if (!subCategory.empty())
{
tempLowerBuffer.assign(subCategory);
std::transform(tempLowerBuffer.begin(), tempLowerBuffer.end(), tempLowerBuffer.begin(), ::tolower);
tempProgIDBuilder.append(tempLowerBuffer);
}
// Create the crypto provider and start the digest / hash
AutoPtr<CryptoProvider> cryptoProvider;
RETURN_IF_FAILED(CryptoProvider::Create(&cryptoProvider));
RETURN_IF_FAILED(cryptoProvider->StartDigest());
COMMON_BYTES data = { 0 };
data.length = (ULONG)tempProgIDBuilder.size() * sizeof(WCHAR);
data.bytes = (LPBYTE)tempProgIDBuilder.c_str();
RETURN_IF_FAILED(cryptoProvider->DigestData(&data));
// Grab the crypto digest
COMMON_BYTES digest = { 0 };
RETURN_IF_FAILED(cryptoProvider->GetDigest(&digest));
// Ensure the string buffer has enough capacity
std::wstring base32EncodedDigest;
base32EncodedDigest.resize(MaxBase32EncodedStringLength);
// Base 32 encode the bytes of the digest and put them into the string buffer
ULONG base32EncodedDigestCharCount = 0;
RETURN_IF_FAILED(Base32Encoding::GetChars(
digest.bytes,
std::min(digest.length, MaxByteCountOfDigest),
MaxBase32EncodedStringLength,
base32EncodedDigest.data(),
&base32EncodedDigestCharCount));
// Set the length of the string buffer to the appropriate value
base32EncodedDigest.resize(base32EncodedDigestCharCount);
// ProgID name is formed by appending the encoded digest to the "AppX" prefix string
tempProgIDBuilder.clear();
tempProgIDBuilder.append(AppXPrefix);
tempProgIDBuilder.append(base32EncodedDigest.c_str());
// Set the return value
generatedProgId.assign(tempProgIDBuilder.c_str());
return S_OK;
}
HRESULT AutoPlay::GenerateHandlerName(LPWSTR type, const std::wstring handlerNameSeed, std::wstring & generatedHandlerName)
{
// Constants
static const ULONG HashedByteCount = 32; // SHA256 generates 256 hashed bits, which is 32 bytes
static const ULONG Base32EncodedLength = 52; // SHA256 generates 256 hashed bits, which is 52 characters after base 32 encoding (5 bits per character)
std::wstring packageFamilyName = m_msixRequest->GetPackageInfo()->GetPackageFamilyName();
std::wstring applicationId = m_msixRequest->GetPackageInfo()->GetApplicationId();
std::wstring handlerNameBuilder;
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
DWORD hashLength;
BYTE bytes[HashedByteCount];
ULONG base32EncodedDigestCharCount;
std::wstring base32EncodedDigest;
size_t typeLength;
// First, append Package family name and App Id to a std::wstring variable for convenience - lowercase the values so that the comparison
// in future versions or other code will be case insensitive
handlerNameBuilder.append(packageFamilyName);
handlerNameBuilder.append(applicationId);
std::transform(handlerNameBuilder.begin(), handlerNameBuilder.end(), handlerNameBuilder.begin(), ::tolower);
// Next, SHA256 hash the Package family name and Application Id
if (!CryptAcquireContext(&hProv, nullptr, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
{
return HRESULT_FROM_WIN32(GetLastError());
}
if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash))
{
return HRESULT_FROM_WIN32(GetLastError());
}
if (!CryptHashData(hHash, (BYTE *)handlerNameBuilder.c_str(), (DWORD)handlerNameBuilder.size() * sizeof(wchar_t), 0))
{
return HRESULT_FROM_WIN32(GetLastError());
}
hashLength = HashedByteCount;
if (!CryptGetHashParam(hHash, HP_HASHVAL, bytes, &hashLength, 0))
{
return HRESULT_FROM_WIN32(GetLastError());
}
// Ensure the string has enough capacity for the string and a null terminator
base32EncodedDigest.resize(Base32EncodedLength + 1);
// Base 32 encode the bytes of the digest and put them into the string buffer
RETURN_IF_FAILED(Base32Encoding::GetChars(
bytes,
HashedByteCount,
Base32EncodedLength,
base32EncodedDigest.data(),
&base32EncodedDigestCharCount));
// Set the length of the string to the appropriate value
base32EncodedDigest.resize(base32EncodedDigestCharCount);
// Find the length of the type string
RETURN_IF_FAILED(StringCchLength(type, STRSAFE_MAX_CCH, &typeLength));
// Finally, construct the string
handlerNameBuilder.clear();
handlerNameBuilder.append(base32EncodedDigest.c_str());
handlerNameBuilder.append(L"!", 1);
handlerNameBuilder.append(type, (ULONG)typeLength);
handlerNameBuilder.append(L"!", 1);
handlerNameBuilder.append(handlerNameSeed);
// Set the return value
generatedHandlerName.assign(handlerNameBuilder.c_str());
std::transform(generatedHandlerName.begin(), generatedHandlerName.end(), generatedHandlerName.begin(), ::tolower);
return S_OK;
}
HRESULT AutoPlay::ProcessAutoPlayForAdd(AutoPlayObject& autoPlayObject)
{
RegistryKey explorerKey;
RETURN_IF_FAILED(explorerKey.Open(HKEY_LOCAL_MACHINE, explorerRegKeyName.c_str(), KEY_READ | KEY_WRITE));
RegistryKey handlerRootKey;
RETURN_IF_FAILED(explorerKey.CreateSubKey(handlerKeyName.c_str(), KEY_WRITE, &handlerRootKey));
//generatedhandlername
RegistryKey handlerKey;
RETURN_IF_FAILED(handlerRootKey.CreateSubKey(autoPlayObject.generatedhandlerName.c_str(), KEY_WRITE, &handlerKey));
// Keys associated with all types
RETURN_IF_FAILED(handlerKey.SetStringValue(L"Action", autoPlayObject.action));
RETURN_IF_FAILED(handlerKey.SetStringValue(L"Provider", autoPlayObject.provider));
//Get the default icon
RETURN_IF_FAILED(handlerKey.SetStringValue(L"DefaultIcon", autoPlayObject.defaultIcon));
RegistryKey handleEventRootKey;
RETURN_IF_FAILED(explorerKey.CreateSubKey(eventHandlerRootRegKeyName.c_str(), KEY_WRITE, &handleEventRootKey));
RegistryKey handleEventKey;
RETURN_IF_FAILED(handleEventRootKey.CreateSubKey(autoPlayObject.handleEvent.c_str(), KEY_WRITE, &handleEventKey));
RETURN_IF_FAILED(handleEventKey.SetStringValue(autoPlayObject.generatedhandlerName.c_str(), L""));
RETURN_IF_FAILED(handlerKey.SetUInt32Value(L"DesktopAppX", 1));
if (autoPlayObject.autoPlayType == DesktopAppxContent)
{
RETURN_IF_FAILED(handlerKey.SetStringValue(L"InvokeProgID", autoPlayObject.generatedProgId));
RETURN_IF_FAILED(handlerKey.SetStringValue(L"InvokeVerb", autoPlayObject.id));
RegistryKey verbRootKey;
RETURN_IF_FAILED(BuildVerbKey(autoPlayObject.generatedProgId, autoPlayObject.id, verbRootKey));
if (autoPlayObject.dropTargetHandler.size() > 0)
{
RegistryKey dropTargetKey;
RETURN_IF_FAILED(verbRootKey.CreateSubKey(dropTargetRegKeyName.c_str(), KEY_WRITE, &dropTargetKey));
std::wstring regDropTargetHandlerBuilder;
regDropTargetHandlerBuilder.append(L"{");
regDropTargetHandlerBuilder.append(autoPlayObject.dropTargetHandler);
regDropTargetHandlerBuilder.append(L"}");
RETURN_IF_FAILED(dropTargetKey.SetStringValue(L"CLSID", regDropTargetHandlerBuilder));
}
else
{
RETURN_IF_FAILED(verbRootKey.SetStringValue(L"AppUserModelID", autoPlayObject.appUserModelId));
std::wstring resolvedExecutableFullPath = m_msixRequest->GetPackageDirectoryPath() + L"\\" + m_msixRequest->GetPackageInfo()->GetRelativeExecutableFilePath();
RETURN_IF_FAILED(verbRootKey.SetStringValue(L"PackageRelativeExecutable", resolvedExecutableFullPath));
RETURN_IF_FAILED(verbRootKey.SetStringValue(L"Parameters", autoPlayObject.parameters));
RETURN_IF_FAILED(verbRootKey.SetStringValue(L"ContractId", L"Windows.File"));
RETURN_IF_FAILED(verbRootKey.SetUInt32Value(L"DesiredInitialViewState", 0));
RETURN_IF_FAILED(verbRootKey.SetStringValue(L"PackageId", m_msixRequest->GetPackageFullName()));
RegistryKey commandKey;
RETURN_IF_FAILED(verbRootKey.CreateSubKey(commandKeyRegName.c_str(), KEY_WRITE, &commandKey));
RETURN_IF_FAILED(commandKey.SetStringValue(L"DelegateExecute", desktopAppXProtocolDelegateExecuteValue));
}
}
else if (autoPlayObject.autoPlayType == DesktopAppxDevice)
{
std::wstring regHWEventHandlerBuilder;
regHWEventHandlerBuilder.append(L"{");
regHWEventHandlerBuilder.append(autoPlayObject.hwEventHandler);
regHWEventHandlerBuilder.append(L"}");
RETURN_IF_FAILED(handlerKey.SetStringValue(L"CLSID", regHWEventHandlerBuilder));
RETURN_IF_FAILED(handlerKey.SetStringValue(L"InitCmdLine", autoPlayObject.initCmdLine));
}
return S_OK;
}
HRESULT AutoPlay::BuildVerbKey(std::wstring generatedProgId, std::wstring id, RegistryKey & verbRootKey)
{
RegistryKey classesRootKey;
RETURN_IF_FAILED(classesRootKey.Open(HKEY_LOCAL_MACHINE, classesKeyPath.c_str(), KEY_READ | KEY_WRITE | WRITE_DAC));
RegistryKey progIdRootKey;
RETURN_IF_FAILED(classesRootKey.CreateSubKey(generatedProgId.c_str(), KEY_READ | KEY_WRITE, &progIdRootKey));
RegistryKey shellRootKey;
RETURN_IF_FAILED(progIdRootKey.CreateSubKey(shellKeyName.c_str(), KEY_READ | KEY_WRITE, &shellRootKey));
RETURN_IF_FAILED(shellRootKey.CreateSubKey(id.c_str(), KEY_READ | KEY_WRITE, &verbRootKey));
return S_OK;
}
HRESULT AutoPlay::CreateHandler(MsixRequest * msixRequest, IPackageHandler ** instance)
{
std::unique_ptr<AutoPlay > localInstance(new AutoPlay(msixRequest));
if (localInstance == nullptr)
{
return E_OUTOFMEMORY;
}
RETURN_IF_FAILED(localInstance->ParseManifest());
*instance = localInstance.release();
return S_OK;
}

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

@ -0,0 +1,63 @@
#pragma once
#include "GeneralUtil.hpp"
#include "IPackageHandler.hpp"
#include "MsixRequest.hpp"
namespace MsixCoreLib
{
enum AutoPlayType
{
InvalidAutoPlayType = 0,
DesktopAppxContent,
DesktopAppxDevice
};
/// the autoplay structure
struct AutoPlayObject
{
std::wstring id;
std::wstring action;
std::wstring handleEvent;
std::wstring provider;
std::wstring defaultIcon;
std::wstring appUserModelId;
std::wstring generatedProgId;
std::wstring generatedhandlerName;
std::wstring dropTargetHandler;
std::wstring parameters;
std::wstring hwEventHandler;
std::wstring initCmdLine;
AutoPlayType autoPlayType;
};
class AutoPlay : IPackageHandler
{
public:
HRESULT ExecuteForAddRequest();
HRESULT ExecuteForRemoveRequest();
static const PCWSTR HandlerName;
static HRESULT CreateHandler(_In_ MsixRequest* msixRequest, _Out_ IPackageHandler** instance);
private:
MsixRequest * m_msixRequest = nullptr;
std::vector<AutoPlayObject> m_autoPlay;
AutoPlay() {}
AutoPlay(_In_ MsixRequest* msixRequest) : m_msixRequest(msixRequest) {}
HRESULT ParseManifest();
HRESULT ProcessAutoPlayForAdd(AutoPlayObject& autoPlayObject);
HRESULT ProcessAutoPlayForRemove(AutoPlayObject& autoPlayObject);
HRESULT GenerateProgId(_In_ std::wstring categoryName, _In_opt_ std::wstring subCategory, _Out_ std::wstring & generatedProgId);
HRESULT GenerateHandlerName(_In_ LPWSTR type, _In_ const std::wstring handlerNameSeed, _Out_ std::wstring & generatedHandlerName);
HRESULT BuildVerbKey(_In_ std::wstring generatedProgId, _In_ std::wstring id, _Out_ RegistryKey & verbRootKey);
};
}

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

@ -0,0 +1,160 @@
#include <Windows.h>
#include <Base32Encoding.hpp>
#include "GeneralUtil.hpp"
#include <TraceLoggingProvider.h>
#include "MsixTraceLoggingProvider.hpp"
#include <assert.h>
namespace MsixCoreLib
{
HRESULT Base32Encoding::GetCharCount(
_In_ ULONG byteCount,
_Out_ ULONG* outWCharCount)
{
HRESULT hr = S_OK;
assert(outWCharCount != NULL);
if (byteCount != 0)
{
static const ULONG bitsPerByte = 8;
static const ULONG bitsPerBase32Digit = 5;
ULONG bitCount;
RETURN_IF_FAILED(Multiply(byteCount, bitsPerByte, &bitCount));
*outWCharCount = bitCount / bitsPerBase32Digit;
// We need to round up the division. When there aren't exactly enough bits to fill in the final base32 digit,
// the remaining bits are set to zero.
if (bitCount % bitsPerBase32Digit > 0)
{
++*outWCharCount;
}
}
else
{
*outWCharCount = 0;
}
return hr;
}
HRESULT Base32Encoding::GetChars(
_In_reads_(byteCount) const BYTE* bytes,
_In_ ULONG byteCount,
_In_ ULONG maxWCharCount,
__out_ecount_part_opt(maxWCharCount, *outWCharCount) WCHAR* wchars,
__out_range(0, maxWCharCount) ULONG* outWCharCount)
{
HRESULT hr = S_OK;
assert(bytes != NULL);
assert(wchars != NULL);
assert(outWCharCount != NULL);
ULONG wcharCount = 0;
ULONG wcharsIdx = 0;
RETURN_IF_FAILED(GetCharCount(byteCount, &wcharCount));
if (wcharCount > maxWCharCount)
{
return HRESULT_FROM_WIN32(E_INVALIDARG);
}
// Consider groups of five bytes. This is the smallest number of bytes that has a number of bits
// that's evently divisible by five.
// Every five bits starting with the most significant of the first byte are made into a base32 value.
// Each value is used to index into the alphabet array to produce a base32 digit.
// When out of bytes but the corresponding base32 value doesn't yet have five bits, 0 is used.
// Normally in these cases a particular number of '=' characters are appended to the resulting base32
// string to indicate how many bits didn't come from the actual byte value. For our purposes no
// such padding characters are necessary.
//
// Bytes: aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee
// Base32 Values: 000aaaaa 000aaabb 000bbbbb 000bcccc 000ccccd 000ddddd 000ddeee 000eeeee
//
// Combo of byte a & F8 a & 07 b & 3E b & 01 c & 0F d & 7C d & 03 e & 1F
// values except b & C0 c & F0 d & 80 e & E0
// for shifting
// Make sure the following math doesn't overflow.
if (maxWCharCount > MaxValue / sizeof(*wchars))
{
return HRESULT_FROM_WIN32(E_INVALIDARG);
}
DebugFillMemory(wchars, maxWCharCount * sizeof(*wchars));
for (ULONG byteIdx = 0; byteIdx < byteCount; byteIdx += 5)
{
BYTE firstByte = bytes[byteIdx];
BYTE secondByte = (byteIdx + 1) < byteCount ? bytes[byteIdx + 1] : 0;
__assume(wcharsIdx + 2 <= wcharCount);
wchars[wcharsIdx++] = ValueToDigit((firstByte & 0xF8) >> 3);
wchars[wcharsIdx++] = ValueToDigit(
((firstByte & 0x07) << 2) | ((secondByte & 0xC0) >> 6));
if (byteIdx + 1 < byteCount)
{
BYTE thirdByte = (byteIdx + 2) < byteCount ? bytes[byteIdx + 2] : 0;
__assume(wcharsIdx + 2 <= wcharCount);
wchars[wcharsIdx++] = ValueToDigit((secondByte & 0x3E) >> 1);
wchars[wcharsIdx++] = ValueToDigit(
((secondByte & 0x01) << 4) | ((thirdByte & 0xF0) >> 4));
if (byteIdx + 2 < byteCount)
{
BYTE fourthByte = (byteIdx + 3) < byteCount ? bytes[byteIdx + 3] : 0;
__assume(wcharsIdx + 1 <= wcharCount);
wchars[wcharsIdx++] = ValueToDigit(
((thirdByte & 0x0F) << 1) | ((fourthByte & 0x80) >> 7));
if (byteIdx + 3 < byteCount)
{
BYTE fifthByte = (byteIdx + 4) < byteCount ? bytes[byteIdx + 4] : 0;
__assume(wcharsIdx + 2 <= wcharCount);
wchars[wcharsIdx++] = ValueToDigit((fourthByte & 0x7C) >> 2);
wchars[wcharsIdx++] = ValueToDigit(
((fourthByte & 0x03) << 3) | ((fifthByte & 0xE0) >> 5));
if (byteIdx + 4 < byteCount)
{
__assume(wcharsIdx + 1 <= wcharCount);
wchars[wcharsIdx++] = ValueToDigit(fifthByte & 0x1F);
}
}
}
}
}
*outWCharCount = wcharCount;
return hr;
}
WCHAR Base32Encoding::ValueToDigit(
_In_ BYTE value)
{
assert(value < 0x20);
// Douglas Crockford's base 32 alphabet variant is 0-9, A-Z except for i, l, o, and u.
static const WCHAR base32DigitList[] = L"0123456789abcdefghjkmnpqrstvwxyz";
C_ASSERT(ARRAYSIZE(base32DigitList) == 0x20 + 1); // Plus one due to NULL terminator
return base32DigitList[value];
}
HRESULT Base32Encoding::Multiply(ULONG d1, ULONG d2, ULONG * result)
{
(*result) = d1 * d2;
if ((d2 == 0 || d1 <= MaxValue / d2))
{
return NOERROR;
}
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
}
}

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

@ -0,0 +1,39 @@
#pragma once
#include "GeneralUtil.hpp"
#define DebugFillMemory(pv, cb)
namespace MsixCoreLib
{
class Base32Encoding
{
public:
static const ULONG MaxValue = 0xFFFFFFFF;
static HRESULT GetCharCount(
_In_ ULONG byteCount,
_Out_ ULONG* outWCharCount);
// The resulting string is not NULL terminated and
// the base32 string produced does not use trailing padding characters.
// This means that the result is not decodable unless the original number
// of bytes is known.
static HRESULT GetChars(
_In_reads_(byteCount) const BYTE* bytes,
_In_ ULONG byteCount,
_In_ ULONG maxWCharCount,
__out_ecount_part_opt(maxWCharCount, *outWCharCount) WCHAR* wchars,
__out_range(0, maxWCharCount) ULONG* outWCharCount);
private:
static WCHAR ValueToDigit(
_In_ BYTE value);
static HRESULT Multiply(
_In_ ULONG d1,
_In_ ULONG d2,
_Out_ ULONG *result);
};
}

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

@ -0,0 +1,58 @@
#include <Windows.h>
#include <WinCrypt.h>
#include <BcryptLibrary.hpp>
#include <assert.h>
/// @note We intentionally load BCRYPT once on first use and never explicitly unload it;
/// it's intentionally kept loaded until process termination unloads it for us.
///
/// @note We initialize the module handle to nullptr @ compile-time and only Load() modifies it,
/// and then only on first need.
///
/// @note In the exceedingly rare event 2 threads concurrently call Load(), we'd call
/// LoadLibrary() twice but producing the same result (the 2nd call finds the DLL already
/// in the LoadedModuleTable and returns the same handle after bumping its reference
/// count). Thus we don't need any special synchronization to manage this, as worst case
/// we'll wind up overwriting the global with the same value on the 2nd load.
volatile PVOID MsixCoreLib::BcryptLibrary::bcryptModule = nullptr;
FARPROC MsixCoreLib::BcryptLibrary::functions[MsixCoreLib::BcryptLibrary::FunctionCount];
PCSTR MsixCoreLib::BcryptLibrary::functionNames[MsixCoreLib::BcryptLibrary::FunctionCount] = {
"BCryptOpenAlgorithmProvider",
"BCryptCloseAlgorithmProvider",
"BCryptGetProperty",
"BCryptCreateHash",
"BCryptHashData",
"BCryptFinishHash",
"BCryptDestroyHash"
};
_Check_return_ HRESULT MsixCoreLib::BcryptLibrary::Load()
{
if (ReadPointerAcquire(&bcryptModule) == nullptr)
{
HMODULE h = LoadLibraryExW(L"Bcrypt.dll", nullptr, 0);
if (h == nullptr)
{
_Analysis_assume_(GetLastError() != ERROR_SUCCESS);
return HRESULT_FROM_WIN32(GetLastError());
}
C_ASSERT(ARRAYSIZE(functions) == ARRAYSIZE(functionNames));
FARPROC exports[ARRAYSIZE(functions)];
for (size_t i = 0; i < ARRAYSIZE(functions); ++i)
{
exports[i] = GetProcAddress(h, functionNames[i]);
if (exports[i] == nullptr)
{
DWORD lastError = GetLastError();
_Analysis_assume_(lastError != ERROR_SUCCESS);
assert(FreeLibrary(h));
return HRESULT_FROM_WIN32(lastError);
}
}
CopyMemory(functions, exports, sizeof(functions));
WritePointerRelease(&bcryptModule, h);
}
return S_OK;
}

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

@ -0,0 +1,116 @@
#pragma once
#include <assert.h>
///@note All functions are pretty much passthru to BCRYPT.DLL so prototypes are identical to BCRYPT.H
/// and not necessarily compliant with AppX Coding Standards (e.g. Hungarian Notation).
namespace MsixCoreLib
{
class BcryptLibrary
{
private:
enum
{
OpenAlgorithmProviderFunction = 0,
CloseAlgorithmProviderFunction,
GetPropertyFunction,
CreateHashFunction,
HashDataFunction,
FinishHashFunction,
DestroyHashFunction,
FunctionCount
};
private:
static volatile PVOID bcryptModule;
static FARPROC functions[FunctionCount];
static PCSTR functionNames[FunctionCount];
public:
static _Check_return_ HRESULT Load();
inline static _Must_inspect_result_ NTSTATUS BCryptOpenAlgorithmProvider(
_Out_ BCRYPT_ALG_HANDLE* phAlgorithm,
_In_ PCWSTR pszAlgId,
_In_opt_ PCWSTR pszImplementation,
_In_ ULONG dwFlags)
{
FARPROC function = functions[OpenAlgorithmProviderFunction];
assert(function != NULL);
return (((NTSTATUS(WINAPI*) (BCRYPT_ALG_HANDLE*, PCWSTR, PCWSTR, ULONG))
(function)))(phAlgorithm, pszAlgId, pszImplementation, dwFlags);
}
inline static NTSTATUS BCryptCloseAlgorithmProvider(
_Inout_ BCRYPT_ALG_HANDLE hAlgorithm,
_In_ ULONG dwFlags)
{
FARPROC function = functions[CloseAlgorithmProviderFunction];
assert(function != NULL);
return (((NTSTATUS(WINAPI*)(BCRYPT_ALG_HANDLE, ULONG))(function)))(hAlgorithm, dwFlags);
}
inline static NTSTATUS BCryptGetProperty(
_In_ BCRYPT_HANDLE hObject,
_In_ PCWSTR pszProperty,
_Out_writes_bytes_to_opt_(cbOutput, *pcbResult) PUCHAR pbOutput,
_In_ ULONG cbOutput,
_Out_ ULONG* pcbResult,
_In_ ULONG dwFlags)
{
FARPROC function = functions[GetPropertyFunction];
assert(function != NULL);
#pragma prefast(suppress:26045, "Annotations on function pointers don't work")
return (((NTSTATUS(WINAPI*)(BCRYPT_HANDLE, PCWSTR, PUCHAR, ULONG, ULONG*, ULONG))
(function)))(hObject, pszProperty, pbOutput, cbOutput, pcbResult, dwFlags);
}
inline static _Must_inspect_result_ NTSTATUS BCryptCreateHash(
_Inout_ BCRYPT_ALG_HANDLE hAlgorithm,
_Out_ BCRYPT_HASH_HANDLE* phHash,
_Out_writes_bytes_all_opt_(cbHashObject) PUCHAR pbHashObject,
_In_ ULONG cbHashObject,
_In_reads_bytes_opt_(cbSecret) PUCHAR pbSecret,
_In_ ULONG cbSecret,
_In_ ULONG dwFlags)
{
FARPROC function = functions[CreateHashFunction];
assert(function != NULL);
return (((NTSTATUS(WINAPI*)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE*, PUCHAR, ULONG, PUCHAR, ULONG, ULONG))
(function)))(hAlgorithm, phHash, pbHashObject, cbHashObject, pbSecret, cbSecret, dwFlags);
}
inline static _Must_inspect_result_ NTSTATUS BCryptHashData(
_Inout_ BCRYPT_HASH_HANDLE hHash,
_In_reads_bytes_(cbInput) PUCHAR pbInput,
_In_ ULONG cbInput,
_In_ ULONG dwFlags)
{
FARPROC function = functions[HashDataFunction];
assert(function != NULL);
return (((NTSTATUS(WINAPI*)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG))
(function)))(hHash, pbInput, cbInput, dwFlags);
}
inline static _Must_inspect_result_ NTSTATUS BCryptFinishHash(
_Inout_ BCRYPT_HASH_HANDLE hHash,
_Out_writes_bytes_all_(cbOutput) PUCHAR pbOutput,
_In_ ULONG cbOutput,
_In_ ULONG dwFlags)
{
FARPROC function = functions[FinishHashFunction];
assert(function != NULL);
return (((NTSTATUS(WINAPI*)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG))
(function)))(hHash, pbOutput, cbOutput, dwFlags);
}
inline static NTSTATUS BCryptDestroyHash(
_Inout_ BCRYPT_HASH_HANDLE hHash)
{
FARPROC function = functions[DestroyHashFunction];
assert(function != NULL);
return (((NTSTATUS(WINAPI*)(BCRYPT_HASH_HANDLE))(function)))(hHash);
}
};
}

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

@ -60,6 +60,7 @@ static const std::wstring appendMenuFlagAttribute = L"AppendMenuFlag";
static const std::wstring oleVerbFlagAttribute = L"OleVerbFlag";
static const std::wstring resourceIndexAttribute = L"ResourceIndex";
static const std::wstring taskIdAttribute = L"TaskId";
static const std::wstring IdAttribute = L"Id";
static const std::wstring extensionQuery = L"/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='Extensions']/*[local-name()='Extension']";
static const std::wstring ftaQuery = L"*[local-name()='FileTypeAssociation']";
@ -88,6 +89,10 @@ static const std::wstring defaultIconQuery = L"*[local-name()='DefaultIcon']";
static const std::wstring toolboxBitmapQuery = L"*[local-name()='ToolboxBitmap32']";
static const std::wstring comVerbQuery = L"*[local-name()='Verbs']/*[local-name()='Verb']";
static const std::wstring startupTaskQuery = L"*[local-name()='StartupTask']";
static const std::wstring launchActionQuery = L"*[local-name()='AutoPlayContent']/*[local-name()='LaunchAction']";
static const std::wstring invokeActionQuery = L"*[local-name()='AutoPlayHandler']/*[local-name()='InvokeAction']";
static const std::wstring invokeActionContentQuery = L"*[local-name()='Content']";
static const std::wstring invokeActionDeviceQuery = L"*[local-name()='Device']";
/// Constants for Firewall DEH
static const std::wstring firewallExtensionQuery = L"/*[local-name()='Package']/*[local-name()='Extensions']/*[local-name()='Extension']/*[local-name()='FirewallRules']/*[local-name()='Rule']";
@ -101,6 +106,29 @@ static const std::wstring remotePortMaxAttribute = L"RemotePortMax";
static const std::wstring directionIn = L"in";
static const std::wstring directionOut = L"out";
/// Constants for AutoPlay DEH
static const std::wstring desktopAppXExtensionCategory = L"windows.autoPlayHandler";
static const std::wstring desktopAppXContentSubCategory = L"Windows.AutoPlayDesktopAppX.Content";
static const std::wstring desktopAppXDeviceSubCategory = L"Windows.AutoPlayDesktopAppX.Device";
static const std::wstring idAttributeName = L"Verb";
static const std::wstring actionAttributeName = L"ActionDisplayName";
static const std::wstring providerAttributeName = L"ProviderDisplayName";
static const std::wstring contentEventAttributeName = L"ContentEvent";
static const std::wstring deviceEventAttributeName = L"DeviceEvent";
static const std::wstring dropTargetHandlerAttributeName = L"DropTargetHandler";
static const std::wstring parametersAttributeName = L"Parameters";
static const std::wstring hwEventHandlerAttributeName = L"HWEventHandler";
static const std::wstring InitCmdLineAttributeName = L"InitCmdLine";
static const std::wstring dropTargetRegKeyName = L"DropTarget";
static const std::wstring commandKeyRegName = L"command";
static const wchar_t desktopAppXProtocolDelegateExecuteValue[] = L"{BFEC0C93-0B7D-4F2C-B09C-AFFFC4BDAE78}";
static const std::wstring explorerRegKeyName = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer";
static const std::wstring handlerKeyName = L"AutoPlayHandlers\\Handlers";
static const std::wstring eventHandlerRootRegKeyName = L"AutoPlayHandlers\\EventHandlers";
static const std::wstring clsidKeyName = L"CLSID";
static const std::wstring inprocHandlerKeyName = L"InprocHandler32";
static const std::wstring defaultInprocHandler = L"ole32.dll";

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

@ -0,0 +1,180 @@
#include <Windows.h>
#include <WinCrypt.h>
#include <BcryptLibrary.hpp>
#include "GeneralUtil.hpp"
#include <CryptoProvider.hpp>
#include <TraceLoggingProvider.h>
#include "MsixTraceLoggingProvider.hpp"
namespace MsixCoreLib
{
CryptoProvider::CryptoProvider()
{
this->providerHandle = NULL;
this->hashHandle = NULL;
this->digest.bytes = NULL;
this->digest.length = 0;
}
CryptoProvider::~CryptoProvider()
{
Reset();
}
void CryptoProvider::Reset()
{
this->digest.bytes = NULL;
this->digest.length = 0;
if (NULL != this->hashHandle)
{
if (!SUCCEEDED(BcryptLibrary::BCryptDestroyHash(this->hashHandle)))
{
return;
}
this->hashHandle = NULL;
}
if (NULL != this->providerHandle)
{
if (!SUCCEEDED(BcryptLibrary::BCryptCloseAlgorithmProvider(this->providerHandle, 0)))
{
return;
}
this->providerHandle = NULL;
}
}
HRESULT CryptoProvider::Create(
_Outptr_ CryptoProvider** provider)
{
RETURN_IF_FAILED(BcryptLibrary::Load());
std::unique_ptr<CryptoProvider> cp(new APPXCOMMON_NEW_TAG CryptoProvider());
if (cp == nullptr)
{
return HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
}
*provider = cp.release();
return S_OK;
}
HRESULT CryptoProvider::OpenProvider()
{
PCWSTR algorithmId = BCRYPT_SHA256_ALGORITHM;
PCWSTR implementation = NULL;
ULONG flags = 0;
BcryptLibrary::BCryptOpenAlgorithmProvider(
&this->providerHandle,
algorithmId,
implementation,
flags);
return S_OK;
}
HRESULT CryptoProvider::StartDigest()
{
BYTE* hashObject;
ULONG hashObjectSize;
ULONG resultSize;
RETURN_IF_FAILED(OpenProvider());
BcryptLibrary::BCryptGetProperty(
this->providerHandle,
BCRYPT_OBJECT_LENGTH,
(PUCHAR)&hashObjectSize,
sizeof(hashObjectSize),
&resultSize,
0);
if (sizeof(this->quickHashObjectBuffer) >= hashObjectSize)
{
hashObject = this->quickHashObjectBuffer;
}
else
{
hashObject = hashObjectBuffer.data();
}
BcryptLibrary::BCryptCreateHash(
this->providerHandle,
&this->hashHandle,
hashObject,
hashObjectSize,
NULL,
NULL,
0);
return S_OK;
}
HRESULT CryptoProvider::DigestData(
_In_ const COMMON_BYTES* data)
{
BcryptLibrary::BCryptHashData(
this->hashHandle,
data->bytes,
data->length,
0);
return S_OK;
}
HRESULT CryptoProvider::GetDigest(
_Out_ COMMON_BYTES* digest)
{
BYTE* digestPtr;
ULONG digestSize;
if (0 == this->digest.length)
{
NTSTATUS status;
ULONG resultSize;
status = BcryptLibrary::BCryptGetProperty(
this->providerHandle,
BCRYPT_HASH_LENGTH,
(PUCHAR)&digestSize,
sizeof(digestSize),
&resultSize,
0);
if (FAILED(HRESULT_FROM_NT(status)))
{
return HRESULT_FROM_NT(status);
}
if (sizeof(this->quickDigestBuffer) >= digestSize)
{
digestPtr = this->quickDigestBuffer;
}
else
{
digestPtr = this->digestBuffer.data();
}
status = BcryptLibrary::BCryptFinishHash(
this->hashHandle,
digestPtr,
digestSize,
0);
if (FAILED(HRESULT_FROM_NT(status)))
{
return HRESULT_FROM_NT(status);
}
this->digest.bytes = digestPtr;
this->digest.length = digestSize;
}
*digest = this->digest;
return S_OK;
}
}

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

@ -0,0 +1,49 @@
#pragma once
#include <vector>
#define APPXCOMMON_NEW_TAG (std::nothrow)
namespace MsixCoreLib
{
struct COMMON_BYTES
{
ULONG length;
__field_ecount(length) BYTE* bytes;
};
// CryptoProvider objects are not thread-safe, hence should not be called from multiple threads simultaneously.
// Usage:
// (StartDigest DigestData* GetDigest* Reset)*
class CryptoProvider
{
private:
BCRYPT_ALG_HANDLE providerHandle;
BCRYPT_HASH_HANDLE hashHandle;
std::vector<BYTE> hashObjectBuffer;
std::vector<BYTE> digestBuffer;
BYTE quickHashObjectBuffer[700]; // Tests shows that HMAC with 256-bit or 512-bit keys requires 600+ bytes of hash object space.
BYTE quickDigestBuffer[64]; // accommodates up to 64-byte hashes
COMMON_BYTES digest;
HRESULT OpenProvider();
CryptoProvider();
public:
~CryptoProvider();
void Reset();
HRESULT StartDigest();
HRESULT DigestData(
_In_ const COMMON_BYTES* data);
HRESULT GetDigest(
_Out_ COMMON_BYTES* digest);
static HRESULT Create(
_Outptr_ CryptoProvider** provider);
};
}

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

@ -35,6 +35,7 @@
#include "PrepareDevirtualizedRegistry.hpp"
#include "WriteDevirtualizedRegistry.hpp"
#include "FirewallRules.hpp"
#include "AutoPlay.hpp"
#include "VirtualFileHandler.hpp"
#include "Constants.hpp"
@ -81,7 +82,8 @@ std::map<PCWSTR, AddHandlerInfo> AddHandlers =
{ComServer::HandlerName, {ComServer::CreateHandler, StartupTask::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
{StartupTask::HandlerName, {StartupTask::CreateHandler, FileTypeAssociation::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
{FileTypeAssociation::HandlerName, {FileTypeAssociation::CreateHandler, FirewallRules::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
{FirewallRules::HandlerName, {FirewallRules::CreateHandler, InstallComplete::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
{FirewallRules::HandlerName, {FirewallRules::CreateHandler, AutoPlay::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
{AutoPlay::HandlerName, {AutoPlay::CreateHandler, InstallComplete::HandlerName, ExecuteErrorHandler, ErrorHandler::HandlerName}},
{InstallComplete::HandlerName, {InstallComplete::CreateHandler, nullptr, ExecuteErrorHandler, ErrorHandler::HandlerName}},
{ErrorHandler::HandlerName, {ErrorHandler::CreateHandler, nullptr, ReturnError, nullptr}},
};
@ -98,7 +100,8 @@ std::map<PCWSTR, RemoveHandlerInfo> RemoveHandlers =
{ComServer::HandlerName, {ComServer::CreateHandler, StartupTask::HandlerName, IgnoreAndProcessNextHandler}},
{StartupTask::HandlerName, {StartupTask::CreateHandler, FileTypeAssociation::HandlerName, IgnoreAndProcessNextHandler}},
{FileTypeAssociation::HandlerName, {FileTypeAssociation::CreateHandler, FirewallRules::HandlerName, IgnoreAndProcessNextHandler}},
{FirewallRules::HandlerName, {FirewallRules::CreateHandler, VirtualFileHandler::HandlerName, IgnoreAndProcessNextHandler}},
{FirewallRules::HandlerName, {FirewallRules::CreateHandler, AutoPlay::HandlerName, IgnoreAndProcessNextHandler}},
{AutoPlay::HandlerName, {AutoPlay::CreateHandler, VirtualFileHandler::HandlerName, IgnoreAndProcessNextHandler}},
{VirtualFileHandler::HandlerName, {VirtualFileHandler::CreateHandler, WriteDevirtualizedRegistry::HandlerName, IgnoreAndProcessNextHandler}},
{WriteDevirtualizedRegistry::HandlerName, {WriteDevirtualizedRegistry::CreateHandler, Extractor::HandlerName, IgnoreAndProcessNextHandler}},
{Extractor::HandlerName, {Extractor::CreateHandler, nullptr, IgnoreAndProcessNextHandler}},

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

@ -3,6 +3,7 @@
#include "AppxPackaging.hpp"
#include "MSIXWindows.hpp"
#include "IPackage.hpp"
#include "FilePaths.hpp"
#include <vector>
namespace MsixCoreLib
@ -21,6 +22,7 @@ namespace MsixCoreLib
std::wstring m_publisher;
std::wstring m_publisherName;
std::wstring m_relativeLogoPath;
std::wstring m_packageDirectoryPath;
std::vector<std::wstring> m_capabilities;
ComPtr<IAppxManifestReader> m_manifestReader;
@ -36,6 +38,14 @@ namespace MsixCoreLib
std::wstring GetVersion();
std::wstring GetPublisher() { return m_publisher; }
std::wstring GetPublisherDisplayName() { return m_publisherName; }
std::wstring GetApplicationId() { return m_applicationId; }
std::wstring GetRelativeLogoPath() {
return m_relativeLogoPath;
}
std::wstring GetPackageDirectoryPath() {
m_packageDirectoryPath = FilePathMappings::GetInstance().GetMsixCoreDirectory() + m_packageFullName + L"\\";
return m_packageDirectoryPath;
}
std::vector<std::wstring> GetCapabilities()
{
@ -87,6 +97,8 @@ namespace MsixCoreLib
std::wstring GetPublisher() { return m_publisher; }
std::wstring GetPublisherDisplayName() { return m_publisherName; }
std::unique_ptr<IStream> GetLogo();
std::wstring GetApplicationId() { return m_applicationId; }
std::vector<std::wstring> GetCapabilities()
{
return m_capabilities;
@ -121,6 +133,7 @@ namespace MsixCoreLib
std::wstring GetVersion() { return PackageBase::GetVersion(); }
std::wstring GetPublisher() { return m_publisher; }
std::wstring GetPublisherDisplayName() { return m_publisherName; }
std::wstring GetApplicationId() { return m_applicationId; }
std::unique_ptr<IStream> GetLogo();

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

@ -83,7 +83,7 @@ HRESULT PopulatePackageInfo::ExecuteForRemoveRequest()
std::shared_ptr<InstalledPackage> package;
RETURN_IF_FAILED(GetPackageInfoFromManifest(packageDirectoryPath, MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN, &package));
if (package == nullptr)
{
return E_FAIL;

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

@ -147,4 +147,11 @@ HRESULT RegistryKey::KeyExists(PCWSTR subkey, bool& exists)
return S_OK;
}
return HRESULT_FROM_WIN32(rc);
}
HRESULT RegistryKey::SetUInt32Value(
_In_opt_ PCWSTR name,
_In_ UINT32 value)
{
return SetValue(name, &value, static_cast<DWORD>(sizeof(value)), REG_DWORD);
}

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

@ -129,6 +129,10 @@ public:
_In_ PCWSTR subkey,
_Out_ bool& exists);
HRESULT SetUInt32Value(
_In_opt_ PCWSTR name,
_In_ UINT32 value);
template<typename TAction> static HRESULT EnumKeyAndDoActionForAllSubkeys(
_In_ RegistryKey* registryKey,
_In_ TAction subkeyActionFunction)

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -187,6 +187,10 @@
<ClInclude Include="..\msixmgr\ValidateTargetDeviceFamily.hpp" />
<ClInclude Include="..\msixmgr\FirewallRules.hpp" />
<ClInclude Include="..\msixmgr\Windows10Redirector.hpp" />
<ClInclude Include="..\msixmgr\AutoPlay.hpp" />
<ClInclude Include="..\msixmgr\BcryptLibrary.hpp" />
<ClInclude Include="..\msixmgr\CryptoProvider.hpp" />
<ClInclude Include="..\msixmgr\Base32Encoding.hpp" />
<ClInclude Include="..\msixmgr\VirtualFileHandler.hpp" />
<ClInclude Include="inc\IMsixResponse.hpp" />
<ClInclude Include="inc\DeploymentOptions.hpp" />
@ -227,6 +231,10 @@
<ClCompile Include="..\msixmgr\ValidateTargetDeviceFamily.cpp" />
<ClCompile Include="..\msixmgr\FirewallRules.cpp" />
<ClCompile Include="..\msixmgr\Windows10Redirector.cpp" />
<ClCompile Include="..\msixmgr\AutoPlay.cpp" />
<ClCompile Include="..\msixmgr\BcryptLibrary.cpp" />
<ClCompile Include="..\msixmgr\CryptoProvider.cpp" />
<ClCompile Include="..\msixmgr\Base32Encoding.cpp" />
<ClCompile Include="..\msixmgr\VirtualFileHandler.cpp" />
<ClCompile Include="GeneralUtil.cpp" />
<ClCompile Include="..\msixmgr\MsixResponse.cpp" />