Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ComPlus CUSTOM_ACTION_DECORATION #550

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/ext/ComPlus/ca/cpapproleexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ HRESULT CpiConfigureApplicationRoles(
hr = CpiActionStartMessage(ppwzData, FALSE);
ExitOnFailure(hr, "Failed to send action start message");

// ger count
// get count
int iCnt = 0;
hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
ExitOnFailure(hr, "Failed to read count");
Expand Down Expand Up @@ -218,7 +218,7 @@ HRESULT CpiConfigureUsersInApplicationRoles(
hr = CpiActionStartMessage(ppwzData, FALSE);
ExitOnFailure(hr, "Failed to send action start message");

// ger count
// get count
int iCnt = 0;
hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
ExitOnFailure(hr, "Failed to read count");
Expand Down
20 changes: 10 additions & 10 deletions src/ext/ComPlus/ca/cpapprolesched.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ LPCWSTR vcsApplicationRoleQuery =
enum eApplicationRoleQuery { arqApplicationRole = 1, arqApplication, arqComponent, arqName };

LPCWSTR vcsUserInApplicationRoleQuery =
L"SELECT `UserInApplicationRole`, `ApplicationRole_`, `ComPlusUserInApplicationRole`.`Component_`, `Domain`, `Name` FROM `Wix4ComPlusUserInApplicationRole`, `Wix4User` WHERE `User_` = `User`";
L"SELECT `UserInApplicationRole`, `ApplicationRole_`, `Wix4ComPlusUserInAppRole`.`Component_`, `Domain`, `Name` FROM `Wix4ComPlusUserInAppRole`, `Wix4User` WHERE `User_` = `User`";
LPCWSTR vcsGroupInApplicationRoleQuery =
L"SELECT `GroupInApplicationRole`, `ApplicationRole_`, `ComPlusGroupInApplicationRole`.`Component_`, `Domain`, `Name` FROM `Wix4ComPlusGroupInApplicationRole`, `Wix4Group` WHERE `Group_` = `Group`";
L"SELECT `GroupInApplicationRole`, `ApplicationRole_`, `Wix4ComPlusGroupInAppRole`.`Component_`, `Domain`, `Name` FROM `Wix4ComPlusGroupInAppRole`, `Wix4Group` WHERE `Group_` = `Group`";
enum eTrusteeInApplicationRoleQuery { tiarqUserInApplicationRole = 1, tiarqApplicationRole, tiarqComponent, tiarqDomain, tiarqName };

LPCWSTR vcsApplicationRolePropertyQuery =
L"SELECT `Name`, `Value` FROM `Wix4ComPlusApplicationRoleProperty` WHERE `ApplicationRole_` = ?";
L"SELECT `Name`, `Value` FROM `Wix4ComPlusAppRoleProperty` WHERE `ApplicationRole_` = ?";


// property definitions
Expand Down Expand Up @@ -95,7 +95,7 @@ HRESULT CpiApplicationRolesRead(

// loop through all application roles
hr = WcaOpenExecuteView(vcsApplicationRoleQuery, &hView);
ExitOnFailure(hr, "Failed to execute view on ComPlusApplicationRole table");
ExitOnFailure(hr, "Failed to execute view on Wix4ComPlusApplicationRole table");

while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
{
Expand Down Expand Up @@ -205,7 +205,7 @@ HRESULT CpiApplicationRolesVerifyInstall(
if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)))
continue;

// if the role is referensed and is not a locater, it must be installed
// if the role is referenced and is not a locater, it must be installed
if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationRoleDependency, "An application role is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);

Expand Down Expand Up @@ -235,7 +235,7 @@ HRESULT CpiApplicationRolesVerifyInstall(
switch (er)
{
case IDABORT:
ExitOnFailure(hr = E_FAIL, "An application with a conflictiong name exists, key: %S", pItm->wzKey);
ExitOnFailure(hr = E_FAIL, "An application with a conflicting name exists, key: %S", pItm->wzKey);
break;
case IDRETRY:
break;
Expand Down Expand Up @@ -319,7 +319,7 @@ HRESULT CpiApplicationRolesInstall(
int iActionType;

// add action text
hr = CpiAddActionTextToActionData(L"CreateComPlusApplicationRoles", ppwzActionData);
hr = CpiAddActionTextToActionData(CUSTOM_ACTION_DECORATION(L"CreateComPlusApplicationRoles"), ppwzActionData);
ExitOnFailure(hr, "Failed to add action text to custom action data");

// add count to action data
Expand Down Expand Up @@ -371,7 +371,7 @@ HRESULT CpiApplicationRolesUninstall(
int iActionType;

// add action text
hr = CpiAddActionTextToActionData(L"RemoveComPlusApplicationRoles", ppwzActionData);
hr = CpiAddActionTextToActionData(CUSTOM_ACTION_DECORATION(L"RemoveComPlusApplicationRoles"), ppwzActionData);
ExitOnFailure(hr, "Failed to add action text to custom action data");

// add count to action data
Expand Down Expand Up @@ -477,7 +477,7 @@ HRESULT CpiUsersInApplicationRolesInstall(
int iActionType;

// add action text
hr = CpiAddActionTextToActionData(L"AddUsersToComPlusApplicationRoles", ppwzActionData);
hr = CpiAddActionTextToActionData(CUSTOM_ACTION_DECORATION(L"AddUsersToComPlusApplicationRoles"), ppwzActionData);
ExitOnFailure(hr, "Failed to add action text to custom action data");

// add count to action data
Expand Down Expand Up @@ -529,7 +529,7 @@ HRESULT CpiUsersInApplicationRolesUninstall(
int iActionType;

// add action text
hr = CpiAddActionTextToActionData(L"RemoveUsersFromComPlusAppRoles", ppwzActionData);
hr = CpiAddActionTextToActionData(CUSTOM_ACTION_DECORATION(L"RemoveUsersFromComPlusAppRoles"), ppwzActionData);
ExitOnFailure(hr, "Failed to add action text to custom action data");

// add count to action data
Expand Down
2 changes: 1 addition & 1 deletion src/ext/ComPlus/ca/cpappsched.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ HRESULT CpiApplicationsVerifyInstall(
if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)))
continue;

// if the application is referensed and is not a locater, it must be installed
// if the application is referenced and is not a locater, it must be installed
if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationDependency, "An application is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);

Expand Down
50 changes: 39 additions & 11 deletions src/ext/ComPlus/ca/cpasmexec.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.

#include "precomp.h"

#include <mscoree.h>

// GAC related declarations

Expand Down Expand Up @@ -61,13 +61,11 @@ IAssemblyCache : public IUnknown

typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll);
typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved);
typedef HRESULT (__stdcall *GetFileVersionFnPtr)(LPCWSTR szFilename, _Out_writes_to_opt_(cchBuffer, *dwLength) LPWSTR szBuffer, DWORD cchBuffer, DWORD* dwLength);
typedef HRESULT (__stdcall *CorBindToRuntimeExFnPtr)(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv);


// RegistrationHelper related declarations

static const GUID CLSID_RegistrationHelper =
{ 0x89a86e7b, 0xc229, 0x4008, { 0x9b, 0xaa, 0x2f, 0x5c, 0x84, 0x11, 0xd7, 0xe0 } };

enum eInstallationFlags {
ifConfigureComponentsOnly = 16,
ifFindOrCreateTargetApplication = 4,
Expand Down Expand Up @@ -156,7 +154,8 @@ static HRESULT UnregisterAssembly(
static void InitAssemblyExec();
static void UninitAssemblyExec();
static HRESULT GetRegistrationHelper(
IDispatch** ppiRegHlp
IDispatch** ppiRegHlp,
LPCWSTR pwzAssemblyPath
);
static HRESULT GetAssemblyCacheObject(
IAssemblyCache** ppAssemblyCache
Expand Down Expand Up @@ -722,15 +721,44 @@ static void UninitAssemblyExec()
}

static HRESULT GetRegistrationHelper(
IDispatch** ppiRegHlp
IDispatch** ppiRegHlp,
LPCWSTR pwzAssemblyPath
)
{
HRESULT hr = S_OK;
wchar_t pwzVersion[MAX_PATH];
DWORD pcchVersionLen = MAX_PATH;
ICLRRuntimeHost* runtimeHost = NULL;

if (!ghMscoree)
{
ghMscoree = ::LoadLibraryW(L"mscoree.dll");
ExitOnNull(ghMscoree, hr, E_FAIL, "Failed to load mscoree.dll");
}
GetFileVersionFnPtr GetFileVersion = (GetFileVersionFnPtr)::GetProcAddress(ghMscoree, "GetFileVersion");
ExitOnNull(GetFileVersion, hr, E_FAIL, "Failed to GetProcAddress for 'GetFileVersion' from 'mscoree.dll'");
hr = GetFileVersion(pwzAssemblyPath, pwzVersion, pcchVersionLen, &pcchVersionLen);

if (!gpiRegHlp)
{
CLSID CLSID_RegistrationHelper{};
hr = ::CLSIDFromProgID(OLESTR("System.EnterpriseServices.RegistrationHelper"), &CLSID_RegistrationHelper);
ExitOnFailure(hr, "Failed to identify CLSID for 'System.EnterpriseServices.RegistrationHelper'");

// NOTE: The 'CoreBindToRuntimeEx' method is DEPRECATED in .NET v4.
// HOWEVER, we might be running in an earlier context at this point so we don't want to rely upon stuff that is particularly v4 dependent.
// Even if we are about to try to fire up a v4 runtime.
// The .NET v4 runtime with STARTUP_LOADER_SAFEMODE flag (to disable version checking of loaded assemblies) is what lets us launch the
// RegistrationHelper. The v4 RegistrationHelper is able to register both v4 and v3 assemblies however, so if we can get it, we most as well
// use it.
CorBindToRuntimeExFnPtr CorBindToRuntimeEx = (CorBindToRuntimeExFnPtr)::GetProcAddress(ghMscoree, "CorBindToRuntimeEx");
hr = CorBindToRuntimeEx(L"v4.0.30319", L"wks", STARTUP_LOADER_SAFEMODE, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&runtimeHost);
// we ignore the HRESULT here. If it worked, great, we'll use it moving forward. If it didn't work, we'll end up trying to resort to legacy .NET FW
// when we just try the COM Create below

// create registration helper object
hr = ::CoCreateInstance(CLSID_RegistrationHelper, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&gpiRegHlp);
// This will be created in the .NET FW 4 version if we managed to launch it above, or in the .NET FW <4 version based on the COM dispatch otherwise
hr = ::CoCreateInstance(CLSID_RegistrationHelper, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&gpiRegHlp);
ExitOnFailure(hr, "Failed to create registration helper object");
}

Expand Down Expand Up @@ -883,7 +911,7 @@ static HRESULT RegisterDotNetAssembly(
}

// get registration helper object
hr = GetRegistrationHelper(&piRegHlp);
hr = GetRegistrationHelper(&piRegHlp, pAttrs->pwzDllPath);
ExitOnFailure(hr, "Failed to get registration helper object");

// get dispatch id of InstallAssembly() method
Expand Down Expand Up @@ -979,7 +1007,7 @@ static HRESULT RegisterNativeAssembly(
ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path");

bstrPSDllPath = ::SysAllocString(pAttrs->pwzPSDllPath ? pAttrs->pwzPSDllPath : L"");
ExitOnNull(bstrPSDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path");
ExitOnNull(bstrPSDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for proxy/stub dll path");

// get catalog
hr = CpiExecGetAdminCatalog(&piCatalog);
Expand Down Expand Up @@ -1089,7 +1117,7 @@ static HRESULT UnregisterDotNetAssembly(
ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path");

// get registration helper object
hr = GetRegistrationHelper(&piRegHlp);
hr = GetRegistrationHelper(&piRegHlp, pAttrs->pwzDllPath);
ExitOnFailure(hr, "Failed to get registration helper object");

// get dispatch id of UninstallAssembly() method
Expand Down
2 changes: 1 addition & 1 deletion src/ext/ComPlus/ca/cpasmsched.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ HRESULT CpiAssembliesVerifyInstall(
if (!pItm->fReferencedForInstall && !pItm->iRoleAssignmentsInstallCount && !WcaIsInstalling(pItm->isInstalled, pItm->isAction))
continue;

// if the assembly is referensed, it must be installed
// if the assembly is referenced, it must be installed
if ((pItm->fReferencedForInstall || pItm->iRoleAssignmentsInstallCount) && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
MessageExitOnFailure(hr = E_FAIL, msierrComPlusAssemblyDependency, "An assembly is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);
}
Expand Down
10 changes: 5 additions & 5 deletions src/ext/ComPlus/ca/cpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ extern "C" UINT __stdcall ComPlusInstallExecute(MSIHANDLE hInstall)
if (INVALID_HANDLE_VALUE != hRollbackFile)
::CloseHandle(hRollbackFile);

// unitialize
// uninitialize
CpiExecFinalize();

if (fInitializedCom)
Expand Down Expand Up @@ -258,7 +258,7 @@ extern "C" UINT __stdcall ComPlusInstallExecuteCommit(MSIHANDLE hInstall)
if (INVALID_HANDLE_VALUE != hRollbackFile)
::CloseHandle(hRollbackFile);

// unitialize
// uninitialize
CpiExecFinalize();

if (fInitializedCom)
Expand Down Expand Up @@ -415,7 +415,7 @@ extern "C" UINT __stdcall ComPlusRollbackInstallExecute(MSIHANDLE hInstall)
if (prdSubscriptions)
CpiFreeRollbackDataList(prdSubscriptions);

// unitialize
// uninitialize
CpiExecFinalize();

if (fInitializedCom)
Expand Down Expand Up @@ -521,7 +521,7 @@ extern "C" UINT __stdcall ComPlusUninstallExecute(MSIHANDLE hInstall)
if (INVALID_HANDLE_VALUE != hRollbackFile)
::CloseHandle(hRollbackFile);

// unitialize
// uninitialize
CpiExecFinalize();

if (fInitializedCom)
Expand Down Expand Up @@ -670,7 +670,7 @@ extern "C" UINT __stdcall ComPlusRollbackUninstallExecute(MSIHANDLE hInstall)
if (prdSubscriptions)
CpiFreeRollbackDataList(prdSubscriptions);

// unitialize
// uninitialize
CpiExecFinalize();

if (fInitializedCom)
Expand Down
71 changes: 69 additions & 2 deletions src/ext/ComPlus/ca/cppartexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ static HRESULT ReadPartitionAttributes(
static void FreePartitionAttributes(
CPI_PARTITION_ATTRIBUTES* pAttrs
);
static HRESULT CpiEnsurePartitionsEnabled();
static HRESULT CreatePartition(
CPI_PARTITION_ATTRIBUTES* pAttrs
);
Expand Down Expand Up @@ -71,7 +72,7 @@ HRESULT CpiConfigurePartitions(
hr = CpiActionStartMessage(ppwzData, FALSE);
ExitOnFailure(hr, "Failed to send action start message");

// ger partition count
// get partition count
int iCnt = 0;
hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
ExitOnFailure(hr, "Failed to read count");
Expand Down Expand Up @@ -215,7 +216,7 @@ HRESULT CpiConfigurePartitionUsers(
hr = CpiActionStartMessage(ppwzData, FALSE);
ExitOnFailure(hr, "Failed to send action start message");

// ger partition count
// get partition count
int iCnt = 0;
hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
ExitOnFailure(hr, "Failed to read count");
Expand Down Expand Up @@ -384,6 +385,69 @@ static void FreePartitionAttributes(
CpiFreePropertyList(pAttrs->pPropList);
}

static HRESULT CpiEnsurePartitionsEnabled()
{
HRESULT hr = S_OK;

ICatalogCollection* piLocalComputerColl = NULL;
IDispatch* piDisp = NULL;
ICatalogObject* piLocalComputerObj = NULL;
VARIANT vtVal;
BSTR bsPartitionsEnabledName = ::SysAllocString(L"PartitionsEnabled");
long numChanges = 0;

::VariantInit(&vtVal);

// get collection
hr = CpiExecGetCatalogCollection(L"LocalComputer", &piLocalComputerColl);
ExitOnFailure(hr, "Failed to get catalog collection");

// find object, there will be only one in the LocalComputer collection
hr = piLocalComputerColl->get_Item(0, &piDisp);
ExitOnFailure(hr, "Failed to get object from collection");

hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piLocalComputerObj);
ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");

// and then we get the value of the PartitionsEnabled property
hr = piLocalComputerObj->get_Value(bsPartitionsEnabledName, &vtVal);
if (!vtVal.boolVal)
{
vtVal.boolVal = true;
hr = piLocalComputerObj->put_Value(bsPartitionsEnabledName, vtVal);
ExitOnFailure(hr, "Failed to put value to Enable COM+ PartitionsEnabled property");
hr = piLocalComputerColl->SaveChanges(&numChanges);
ExitOnFailure(hr, "Failed to save PartitionsEnabled property");

// we'll read back the hopefully updated values of the PartitionsEnabled property
// if it's still False, then we're on a Windows Desktop that doesn't allow Partitions
// (as of Windows Server2003 Microsoft limited Partitions to only ServerOS platforms)
hr = piLocalComputerObj->get_Value(bsPartitionsEnabledName, &vtVal);
ExitOnFailure(hr, "Failed to read PartitionsEnabled property");
}

if (vtVal.boolVal)
{
// everything went well, we have the Partitioning available
hr = S_OK;
}
else
{
// we're on a Desktop OS, or couldn't otherwise enable partitioning
WcaLog(LOGMSG_STANDARD, "Failed to Enable COM+ PartitionEnabled property. This suggests Partitioning was attempted on a Desktop OS, which is not supported");
hr = S_FALSE;
}

LExit:
// clean up
ReleaseObject(piLocalComputerColl);
ReleaseObject(piLocalComputerObj);
ReleaseBSTR(bsPartitionsEnabledName);
::VariantClear(&vtVal);

return hr;
}

static HRESULT CreatePartition(
CPI_PARTITION_ATTRIBUTES* pAttrs
)
Expand All @@ -408,6 +472,9 @@ static HRESULT CreatePartition(

if (S_FALSE == hr)
{
hr = CpiEnsurePartitionsEnabled();
ExitOnFailure(hr, "Failed to enable partitions");

// create partition
hr = CpiAddCollectionObject(piPartColl, &piPartObj);
ExitOnFailure(hr, "Failed to add partition to collection");
Expand Down
2 changes: 1 addition & 1 deletion src/ext/ComPlus/ca/cppartroleexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ HRESULT CpiConfigureUsersInPartitionRoles(
hr = CpiActionStartMessage(ppwzData, FALSE);
ExitOnFailure(hr, "Failed to send action start message");

// ger count
// get count
int iCnt = 0;
hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
ExitOnFailure(hr, "Failed to read count");
Expand Down
4 changes: 2 additions & 2 deletions src/ext/ComPlus/ca/cppartrolesched.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ LPCWSTR vcsPartitionRoleQuery =
enum ePartitionRoleQuery { prqPartitionRole = 1, prqPartition, prqComponent, prqName };

LPCWSTR vcsUserInPartitionRoleQuery =
L"SELECT `UserInPartitionRole`, `PartitionRole_`, `ComPlusUserInPartitionRole`.`Component_`, `Domain`, `Name` FROM `Wix4ComPlusUserInPartitionRole`, `Wix4User` WHERE `User_` = `User`";
L"SELECT `UserInPartitionRole`, `PartitionRole_`, `Wix4ComPlusUserInPartitionRole`.`Component_`, `Domain`, `Name` FROM `Wix4ComPlusUserInPartitionRole`, `Wix4User` WHERE `User_` = `User`";
LPCWSTR vcsGroupInPartitionRoleQuery =
L"SELECT `GroupInPartitionRole`, `PartitionRole_`, `ComPlusGroupInPartitionRole`.`Component_`, `Domain`, `Name` FROM `Wix4ComPlusGroupInPartitionRole`, `Wix4Group` WHERE `Group_` = `Group`";
L"SELECT `GroupInPartitionRole`, `PartitionRole_`, `Wix4ComPlusGroupInPartitionRole`.`Component_`, `Domain`, `Name` FROM `Wix4ComPlusGroupInPartitionRole`, `Wix4Group` WHERE `Group_` = `Group`";
enum eTrusteeInPartitionRoleQuery { tiprqUserInPartitionRole = 1, tiprqPartitionRole, tiprqComponent, tiprqDomain, tiprqName };


Expand Down
Loading
Loading