summaryrefslogtreecommitdiff
path: root/src/ext/Util/ca/scaexec.cpp
diff options
context:
space:
mode:
authorBevan Weiss <bevan.weiss@gmail.com>2024-08-04 21:13:44 +1000
committerRob Mensching <rob@firegiant.com>2025-02-11 23:14:49 -0800
commit5b4a6538ee06988c75b717bd905197fb670e6142 (patch)
treeeb078854f258ebdabaf206282d56cbdcf87759ef /src/ext/Util/ca/scaexec.cpp
parent2c5bb89424b12de812498d568bc1aae2d4098e60 (diff)
downloadwix-5b4a6538ee06988c75b717bd905197fb670e6142.tar.gz
wix-5b4a6538ee06988c75b717bd905197fb670e6142.tar.bz2
wix-5b4a6538ee06988c75b717bd905197fb670e6142.zip
Add/Remove Group Membership rollback handled.
Fixups to a few test cases. Signed-off-by: Bevan Weiss <bevan.weiss@gmail.com>
Diffstat (limited to 'src/ext/Util/ca/scaexec.cpp')
-rw-r--r--src/ext/Util/ca/scaexec.cpp128
1 files changed, 80 insertions, 48 deletions
diff --git a/src/ext/Util/ca/scaexec.cpp b/src/ext/Util/ca/scaexec.cpp
index 64f4c823..fea60b01 100644
--- a/src/ext/Util/ca/scaexec.cpp
+++ b/src/ext/Util/ca/scaexec.cpp
@@ -716,7 +716,7 @@ static HRESULT RemoveGroupInternal(
716 // 716 //
717 if (!(SCAG_DONT_CREATE_GROUP & iAttributes)) 717 if (!(SCAG_DONT_CREATE_GROUP & iAttributes))
718 { 718 {
719 GetDomainServerName(wzDomain, &pwzServerName, DS_WRITABLE_REQUIRED); 719 hr = GetDomainFromServerName(&pwzServerName, wzDomain, DS_WRITABLE_REQUIRED);
720 720
721 NET_API_STATUS er = ::NetLocalGroupDel(pwzServerName, wzName); 721 NET_API_STATUS er = ::NetLocalGroupDel(pwzServerName, wzName);
722 hr = HRESULT_FROM_WIN32(er); 722 hr = HRESULT_FROM_WIN32(er);
@@ -1218,9 +1218,13 @@ LExit:
1218 1218
1219 1219
1220/******************************************************************** 1220/********************************************************************
1221 CreateGroup - CUSTOM ACTION ENTRY POINT for creating groups 1221 CreateGroup - CUSTOM ACTION ENTRY POINT for creating groups
1222 For domain parent group, must be run as Impersonated=true
1223 For non-domain parent group, must be run as Impersonated=false (for elevation)
1222 1224
1223 Input: deferred CustomActionData - GroupName\tDomain\tComment\tAttributes 1225 Input: deferred CustomActionData - GroupName\tDomain\tComment\tAttributes\tScriptKey(empty for no rollback)
1226
1227 Output: Script for RollbackCreateGroup - OriginalComment\tRollbackAttributes
1224 * *****************************************************************/ 1228 * *****************************************************************/
1225extern "C" UINT __stdcall CreateGroup( 1229extern "C" UINT __stdcall CreateGroup(
1226 __in MSIHANDLE hInstall 1230 __in MSIHANDLE hInstall
@@ -1281,8 +1285,8 @@ extern "C" UINT __stdcall CreateGroup(
1281 1285
1282 if (!(SCAG_DONT_CREATE_GROUP & iAttributes)) 1286 if (!(SCAG_DONT_CREATE_GROUP & iAttributes))
1283 { 1287 {
1284 hr = GetDomainServerName(pwzDomain, &pwzServerName, DS_WRITABLE_REQUIRED); 1288 hr = GetDomainFromServerName(&pwzServerName, pwzDomain, DS_WRITABLE_REQUIRED);
1285 ExitOnFailure(hr, "failed to find Domain %ls.", pwzDomain); 1289 ExitOnFailure(hr, "failed to find writable server for domain %ls.", pwzDomain);
1286 1290
1287 // Set the group's comment 1291 // Set the group's comment
1288 if (SCAG_REMOVE_COMMENT & iAttributes) 1292 if (SCAG_REMOVE_COMMENT & iAttributes)
@@ -1304,7 +1308,7 @@ extern "C" UINT __stdcall CreateGroup(
1304 { 1308 {
1305 if (SCAG_FAIL_IF_EXISTS & iAttributes) 1309 if (SCAG_FAIL_IF_EXISTS & iAttributes)
1306 { 1310 {
1307 MessageExitOnFailure(hr, msierrGRPFailedGroupCreateExists, "Group (%ls) was not supposed to exist, but does", pwzName); 1311 MessageExitOnFailure(hr, msierrGRPFailedGroupCreateExists, "Group (%ls\\%ls) was not supposed to exist, but does", pwzDomain, pwzName);
1308 } 1312 }
1309 1313
1310 hr = S_OK; // Make sure that we don't report this situation as an error 1314 hr = S_OK; // Make sure that we don't report this situation as an error
@@ -1359,7 +1363,7 @@ extern "C" UINT __stdcall CreateGroup(
1359 hr = SetGroupComment(pwzServerName, pwzName, L""); 1363 hr = SetGroupComment(pwzServerName, pwzName, L"");
1360 if (FAILED(hr)) 1364 if (FAILED(hr))
1361 { 1365 {
1362 WcaLogError(hr, "failed to clear comment for group %ls\\%ls, continuing anyway.", pwzServerName, pwzName); 1366 WcaLogError(hr, "failed to clear comment for group %ls\\%ls, continuing anyway.", pwzDomain, pwzName);
1363 hr = S_OK; 1367 hr = S_OK;
1364 } 1368 }
1365 } 1369 }
@@ -1368,14 +1372,14 @@ extern "C" UINT __stdcall CreateGroup(
1368 hr = SetGroupComment(pwzServerName, pwzName, pwzComment); 1372 hr = SetGroupComment(pwzServerName, pwzName, pwzComment);
1369 if (FAILED(hr)) 1373 if (FAILED(hr))
1370 { 1374 {
1371 WcaLogError(hr, "failed to set comment to %ls for group %ls\\%ls, continuing anyway.", pwzComment, pwzServerName, pwzName); 1375 WcaLogError(hr, "failed to set comment to '%ls' for group %ls\\%ls, continuing anyway.", pwzComment, pwzDomain, pwzName);
1372 hr = S_OK; 1376 hr = S_OK;
1373 } 1377 }
1374 } 1378 }
1375 } 1379 }
1376 } 1380 }
1377 } 1381 }
1378 MessageExitOnFailure(hr, msierrGRPFailedGroupCreate, "failed to create group: %ls", pwzName); 1382 MessageExitOnFailure(hr, msierrGRPFailedGroupCreate, "failed to create group: %ls\\%ls", pwzDomain, pwzName);
1379 } 1383 }
1380 1384
1381LExit: 1385LExit:
@@ -1391,6 +1395,7 @@ LExit:
1391 ReleaseStr(pwzDomain); 1395 ReleaseStr(pwzDomain);
1392 ReleaseStr(pwzComment); 1396 ReleaseStr(pwzComment);
1393 ReleaseStr(pwzScriptKey); 1397 ReleaseStr(pwzScriptKey);
1398 ReleaseStr(pwzServerName);
1394 1399
1395 if (fInitializedCom) 1400 if (fInitializedCom)
1396 { 1401 {
@@ -1412,6 +1417,11 @@ LExit:
1412 1417
1413/******************************************************************** 1418/********************************************************************
1414 CreateGroupRollback - CUSTOM ACTION ENTRY POINT for CreateGroup rollback 1419 CreateGroupRollback - CUSTOM ACTION ENTRY POINT for CreateGroup rollback
1420 For domain parent group, must be run as Impersonated=true
1421 For non-domain parent group, must be run as Impersonated=false (for elevation)
1422
1423 Input: rollback CustomActionData - ScriptKey\tGroupName\tDomain\tComment\tRollbackAttributes
1424 rollback script - OriginalComment\tRollbackAttributes
1415 1425
1416 * *****************************************************************/ 1426 * *****************************************************************/
1417extern "C" UINT __stdcall CreateGroupRollback( 1427extern "C" UINT __stdcall CreateGroupRollback(
@@ -1429,7 +1439,7 @@ extern "C" UINT __stdcall CreateGroupRollback(
1429 LPWSTR pwzName = NULL; 1439 LPWSTR pwzName = NULL;
1430 LPWSTR pwzDomain = NULL; 1440 LPWSTR pwzDomain = NULL;
1431 LPWSTR pwzComment = NULL; 1441 LPWSTR pwzComment = NULL;
1432 int iAttributes = 0; 1442 int iRollbackAttributes = 0;
1433 BOOL fInitializedCom = FALSE; 1443 BOOL fInitializedCom = FALSE;
1434 1444
1435 WCA_CASCRIPT_HANDLE hRollbackScript = NULL; 1445 WCA_CASCRIPT_HANDLE hRollbackScript = NULL;
@@ -1454,7 +1464,7 @@ extern "C" UINT __stdcall CreateGroupRollback(
1454 // 1464 //
1455 pwz = pwzData; 1465 pwz = pwzData;
1456 hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); 1466 hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey);
1457 ExitOnFailure(hr, "failed to read encoding key from custom action data"); 1467 ExitOnFailure(hr, "failed to read script key from custom action data");
1458 1468
1459 hr = WcaReadStringFromCaData(&pwz, &pwzName); 1469 hr = WcaReadStringFromCaData(&pwz, &pwzName);
1460 ExitOnFailure(hr, "failed to read name from custom action data"); 1470 ExitOnFailure(hr, "failed to read name from custom action data");
@@ -1465,8 +1475,8 @@ extern "C" UINT __stdcall CreateGroupRollback(
1465 hr = WcaReadStringFromCaData(&pwz, &pwzComment); 1475 hr = WcaReadStringFromCaData(&pwz, &pwzComment);
1466 ExitOnFailure(hr, "failed to read comment from custom action data"); 1476 ExitOnFailure(hr, "failed to read comment from custom action data");
1467 1477
1468 hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); 1478 hr = WcaReadIntegerFromCaData(&pwz, &iRollbackAttributes);
1469 ExitOnFailure(hr, "failed to read attributes from custom action data"); 1479 ExitOnFailure(hr, "failed to read rollback attributes from custom action data");
1470 1480
1471 // Best effort to read original configuration from CreateUser. 1481 // Best effort to read original configuration from CreateUser.
1472 hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript); 1482 hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript);
@@ -1502,12 +1512,12 @@ extern "C" UINT __stdcall CreateGroupRollback(
1502 } 1512 }
1503 else 1513 else
1504 { 1514 {
1505 iAttributes |= iOriginalAttributes; 1515 iRollbackAttributes |= iOriginalAttributes;
1506 } 1516 }
1507 } 1517 }
1508 } 1518 }
1509 1519
1510 hr = RemoveGroupInternal(pwzDomain, pwzName, iAttributes); 1520 hr = RemoveGroupInternal(pwzDomain, pwzName, iRollbackAttributes);
1511 1521
1512LExit: 1522LExit:
1513 WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE); 1523 WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE);
@@ -1535,9 +1545,12 @@ LExit:
1535 1545
1536 1546
1537/******************************************************************** 1547/********************************************************************
1538 RemoveGroup - CUSTOM ACTION ENTRY POINT for removing groups 1548 RemoveGroup - CUSTOM ACTION ENTRY POINT for removing groups
1549 For domain parent group, must be run as Impersonated=true
1550 For non-domain parent group, must be run as Impersonated=false (for elevation)
1551 NOTE: This action can't be rolled back, so should only be performed in commit phase
1539 1552
1540 Input: deferred CustomActionData - Name\tDomain 1553 Input: commit CustomActionData - Name\tDomain\tComment\tAttributes
1541 * *****************************************************************/ 1554 * *****************************************************************/
1542extern "C" UINT __stdcall RemoveGroup( 1555extern "C" UINT __stdcall RemoveGroup(
1543 MSIHANDLE hInstall 1556 MSIHANDLE hInstall
@@ -1605,7 +1618,7 @@ LExit:
1605 return WcaFinalize(er); 1618 return WcaFinalize(er);
1606} 1619}
1607 1620
1608HRESULT AlterGroupMembership(bool remove, bool isRollback = false) 1621HRESULT AlterGroupMembership(bool remove, bool isRollback)
1609{ 1622{
1610 HRESULT hr = S_OK; 1623 HRESULT hr = S_OK;
1611 NET_API_STATUS er = ERROR_SUCCESS; 1624 NET_API_STATUS er = ERROR_SUCCESS;
@@ -1617,22 +1630,13 @@ HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
1617 LPWSTR pwzChildName = NULL; 1630 LPWSTR pwzChildName = NULL;
1618 LPWSTR pwzChildDomain = NULL; 1631 LPWSTR pwzChildDomain = NULL;
1619 int iAttributes = 0; 1632 int iAttributes = 0;
1633 LPWSTR pwzScriptKey = NULL;
1620 LPWSTR pwzChildFullName = NULL; 1634 LPWSTR pwzChildFullName = NULL;
1621 LPWSTR pwzServerName = NULL; 1635 LPWSTR pwzServerName = NULL;
1622 LOCALGROUP_MEMBERS_INFO_3 memberInfo3 = {}; 1636 LOCALGROUP_MEMBERS_INFO_3 memberInfo3 = {};
1623 WCA_CASCRIPT_HANDLE phRollbackScript = NULL; 1637 WCA_CASCRIPT_HANDLE hRollbackScript = NULL;
1624 1638
1625 if (isRollback) 1639 hr = WcaGetProperty(L"CustomActionData", &pwzData);
1626 {
1627 // Get a CaScript key
1628 hr = WcaCaScriptOpen(WCA_ACTION_NONE, WCA_CASCRIPT_ROLLBACK, FALSE, remove ? L"AddGroupMembershipRollback" : L"RemoveGroupMembershipRollback", &phRollbackScript);
1629 hr = WcaCaScriptReadAsCustomActionData(phRollbackScript, &pwzData);
1630 }
1631 else
1632 {
1633 hr = WcaCaScriptCreate(WCA_ACTION_NONE, WCA_CASCRIPT_ROLLBACK, FALSE, remove ? L"RemoveGroupMembershipRollback" : L"AddGroupMembershipRollback", TRUE, &phRollbackScript);
1634 hr = WcaGetProperty(L"CustomActionData", &pwzData);
1635 }
1636 ExitOnFailure(hr, "failed to get CustomActionData"); 1640 ExitOnFailure(hr, "failed to get CustomActionData");
1637 1641
1638 WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); 1642 WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData);
@@ -1656,8 +1660,28 @@ HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
1656 hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); 1660 hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
1657 ExitOnFailure(hr, "failed to read attributes from custom action data"); 1661 ExitOnFailure(hr, "failed to read attributes from custom action data");
1658 1662
1659 hr = GetDomainServerName(pwzParentDomain, &pwzServerName, DS_WRITABLE_REQUIRED); 1663 hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey);
1660 ExitOnFailure(hr, "failed to contact domain server %ls", pwzParentDomain); 1664 ExitOnFailure(hr, "failed to read scriptkey from custom action data");
1665
1666 if (isRollback)
1667 {
1668 // if the script file doesn't exist, then we'll abandon this rollback
1669 hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript);
1670 if (S_OK == hr)
1671 {
1672 WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE);
1673 }
1674 else
1675 {
1676 WcaLog(LOGMSG_VERBOSE, "Rollback of parent: %ls\\%ls, child: %ls\\%ls relationship not performed, rollback script not found", pwzParentDomain, pwzParentName, pwzChildDomain, pwzChildName);
1677 hr = S_OK;
1678 ExitFunction();
1679 }
1680 }
1681
1682
1683 hr = GetDomainFromServerName(&pwzServerName, pwzParentDomain, DS_WRITABLE_REQUIRED);
1684 ExitOnFailure(hr, "failed to obtain writable server for domain %ls", pwzParentDomain);
1661 1685
1662 if (*pwzChildDomain) 1686 if (*pwzChildDomain)
1663 { 1687 {
@@ -1679,16 +1703,13 @@ HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
1679 } 1703 }
1680 hr = HRESULT_FROM_WIN32(er); 1704 hr = HRESULT_FROM_WIN32(er);
1681 1705
1706 // if there was no error, the action succeeded, and we should flag that it's something which might need
1707 // to be rolled back
1682 if (S_OK == hr && !isRollback) 1708 if (S_OK == hr && !isRollback)
1683 { 1709 {
1684 // we need to log rollback data, we can just use exactly the same data we used to do the initial action though 1710 // we create a script file, the rollback matching this scriptkey will occur if the file exists
1685 WcaCaScriptWriteString(phRollbackScript, pwzParentName); 1711 hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript);
1686 WcaCaScriptWriteString(phRollbackScript, pwzParentDomain); 1712 WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE);
1687 WcaCaScriptWriteString(phRollbackScript, pwzChildName);
1688 WcaCaScriptWriteString(phRollbackScript, pwzChildDomain);
1689 WcaCaScriptWriteNumber(phRollbackScript, iAttributes);
1690 WcaCaScriptFlush(phRollbackScript);
1691 WcaCaScriptClose(phRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE);
1692 } 1713 }
1693 1714
1694 if (remove) 1715 if (remove)
@@ -1716,6 +1737,7 @@ LExit:
1716 ReleaseStr(pwzChildDomain); 1737 ReleaseStr(pwzChildDomain);
1717 ReleaseStr(pwzChildFullName); 1738 ReleaseStr(pwzChildFullName);
1718 ReleaseStr(pwzServerName); 1739 ReleaseStr(pwzServerName);
1740 ReleaseStr(pwzScriptKey);
1719 1741
1720 if (SCAG_NON_VITAL & iAttributes) 1742 if (SCAG_NON_VITAL & iAttributes)
1721 { 1743 {
@@ -1725,10 +1747,12 @@ LExit:
1725} 1747}
1726 1748
1727/******************************************************************** 1749/********************************************************************
1728 AddGroupmembership - CUSTOM ACTION ENTRY POINT for creating groups 1750 AddGroupMembership - CUSTOM ACTION ENTRY POINT for adding Group Membership
1751 For domain parent group, must be run as Impersonated=true
1752 For non-domain parent group, must be run as Impersonated=false (for elevation)
1729 1753
1730 Input: deferred CustomActionData - 1754 Input: deferred CustomActionData -
1731 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes 1755 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey
1732 * *****************************************************************/ 1756 * *****************************************************************/
1733extern "C" UINT __stdcall AddGroupMembership( 1757extern "C" UINT __stdcall AddGroupMembership(
1734 __in MSIHANDLE hInstall 1758 __in MSIHANDLE hInstall
@@ -1758,10 +1782,13 @@ LExit:
1758} 1782}
1759 1783
1760/******************************************************************** 1784/********************************************************************
1761 AddGroupmembership - CUSTOM ACTION ENTRY POINT for creating groups 1785 AddGroupMembershipRollback - CUSTOM ACTION ENTRY POINT for rolling back
1786 adding Group Membership
1787 For domain parent group, must be run as Impersonated=true
1788 For non-domain parent group, must be run as Impersonated=false (for elevation)
1762 1789
1763 Input: deferred CustomActionData - 1790 Input: deferred CustomActionData -
1764 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes 1791 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey
1765 * *****************************************************************/ 1792 * *****************************************************************/
1766extern "C" UINT __stdcall AddGroupMembershipRollback( 1793extern "C" UINT __stdcall AddGroupMembershipRollback(
1767 __in MSIHANDLE hInstall 1794 __in MSIHANDLE hInstall
@@ -1791,10 +1818,12 @@ LExit:
1791} 1818}
1792 1819
1793/******************************************************************** 1820/********************************************************************
1794 RemoveGroupMembership - CUSTOM ACTION ENTRY POINT for creating groups 1821 RemoveGroupMembership - CUSTOM ACTION ENTRY POINT for removing group memberships
1822 For domain parent group, must be run as Impersonated=true
1823 For non-domain parent group, must be run as Impersonated=false (for elevation)
1795 1824
1796 Input: deferred CustomActionData - 1825 Input: deferred CustomActionData -
1797 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes 1826 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey
1798 * *****************************************************************/ 1827 * *****************************************************************/
1799extern "C" UINT __stdcall RemoveGroupMembership( 1828extern "C" UINT __stdcall RemoveGroupMembership(
1800 __in MSIHANDLE hInstall 1829 __in MSIHANDLE hInstall
@@ -1824,10 +1853,13 @@ LExit:
1824} 1853}
1825 1854
1826/******************************************************************** 1855/********************************************************************
1827 RemoveGroupMembershipRollback - CUSTOM ACTION ENTRY POINT for creating groups 1856 RemoveGroupMembershipRollback - CUSTOM ACTION ENTRY POINT for rolling back
1857 removing group memberships
1858 For domain parent group, must be run as Impersonated=true
1859 For non-domain parent group, must be run as Impersonated=false (for elevation)
1828 1860
1829 Input: deferred CustomActionData - 1861 Input: deferred CustomActionData -
1830 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes 1862 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey
1831 * *****************************************************************/ 1863 * *****************************************************************/
1832extern "C" UINT __stdcall RemoveGroupMembershipRollback( 1864extern "C" UINT __stdcall RemoveGroupMembershipRollback(
1833 __in MSIHANDLE hInstall 1865 __in MSIHANDLE hInstall