diff options
Diffstat (limited to '')
17 files changed, 346 insertions, 134 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 | * *****************************************************************/ |
| 1225 | extern "C" UINT __stdcall CreateGroup( | 1229 | extern "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 | ||
| 1381 | LExit: | 1385 | LExit: |
| @@ -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 | * *****************************************************************/ |
| 1417 | extern "C" UINT __stdcall CreateGroupRollback( | 1427 | extern "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 | ||
| 1512 | LExit: | 1522 | LExit: |
| 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 | * *****************************************************************/ |
| 1542 | extern "C" UINT __stdcall RemoveGroup( | 1555 | extern "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 | ||
| 1608 | HRESULT AlterGroupMembership(bool remove, bool isRollback = false) | 1621 | HRESULT 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 | * *****************************************************************/ |
| 1733 | extern "C" UINT __stdcall AddGroupMembership( | 1757 | extern "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 | * *****************************************************************/ |
| 1766 | extern "C" UINT __stdcall AddGroupMembershipRollback( | 1793 | extern "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 | * *****************************************************************/ |
| 1799 | extern "C" UINT __stdcall RemoveGroupMembership( | 1828 | extern "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 | * *****************************************************************/ |
| 1832 | extern "C" UINT __stdcall RemoveGroupMembershipRollback( | 1864 | extern "C" UINT __stdcall RemoveGroupMembershipRollback( |
| 1833 | __in MSIHANDLE hInstall | 1865 | __in MSIHANDLE hInstall |
diff --git a/src/ext/Util/ca/scagroup.cpp b/src/ext/Util/ca/scagroup.cpp index 699d9db7..bab438ea 100644 --- a/src/ext/Util/ca/scagroup.cpp +++ b/src/ext/Util/ca/scagroup.cpp | |||
| @@ -220,13 +220,13 @@ HRESULT ScaGroupGetParents( | |||
| 220 | ExitOnFailure(hr, "failed to get Component state for Wix4Group"); | 220 | ExitOnFailure(hr, "failed to get Component state for Wix4Group"); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | hr = WcaGetRecordString(hRec, vgpqParentName, &pwzTempStr); | 223 | hr = WcaGetRecordFormattedString(hRec, vgpqParentName, &pwzTempStr); |
| 224 | ExitOnFailure(hr, "failed to get Wix4Group.Name"); | 224 | ExitOnFailure(hr, "failed to get Wix4Group.Name"); |
| 225 | wcsncpy_s(psgParent->wzName, pwzTempStr, MAX_DARWIN_COLUMN); | 225 | wcsncpy_s(psgParent->wzName, pwzTempStr, MAX_DARWIN_COLUMN); |
| 226 | ReleaseNullStr(pwzTempStr); | 226 | ReleaseNullStr(pwzTempStr); |
| 227 | 227 | ||
| 228 | 228 | ||
| 229 | hr = WcaGetRecordString(hRec, vgpqParentDomain, &pwzTempStr); | 229 | hr = WcaGetRecordFormattedString(hRec, vgpqParentDomain, &pwzTempStr); |
| 230 | ExitOnFailure(hr, "failed to get Wix4Group.Domain"); | 230 | ExitOnFailure(hr, "failed to get Wix4Group.Domain"); |
| 231 | wcsncpy_s(psgParent->wzDomain, pwzTempStr, MAX_DARWIN_COLUMN); | 231 | wcsncpy_s(psgParent->wzDomain, pwzTempStr, MAX_DARWIN_COLUMN); |
| 232 | ReleaseNullStr(pwzTempStr); | 232 | ReleaseNullStr(pwzTempStr); |
| @@ -288,13 +288,13 @@ HRESULT ScaGroupGetChildren( | |||
| 288 | ExitOnFailure(hr, "failed to get Component state for Wix4Group"); | 288 | ExitOnFailure(hr, "failed to get Component state for Wix4Group"); |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | hr = WcaGetRecordString(hRec, vgcqChildName, &pwzTempStr); | 291 | hr = WcaGetRecordFormattedString(hRec, vgcqChildName, &pwzTempStr); |
| 292 | ExitOnFailure(hr, "failed to get Wix4Group.Name"); | 292 | ExitOnFailure(hr, "failed to get Wix4Group.Name"); |
| 293 | wcsncpy_s(psgChild->wzName, pwzTempStr, MAX_DARWIN_COLUMN); | 293 | wcsncpy_s(psgChild->wzName, pwzTempStr, MAX_DARWIN_COLUMN); |
| 294 | ReleaseNullStr(pwzTempStr); | 294 | ReleaseNullStr(pwzTempStr); |
| 295 | 295 | ||
| 296 | 296 | ||
| 297 | hr = WcaGetRecordString(hRec, vgcqChildDomain, &pwzTempStr); | 297 | hr = WcaGetRecordFormattedString(hRec, vgcqChildDomain, &pwzTempStr); |
| 298 | ExitOnFailure(hr, "failed to get Wix4Group.Domain"); | 298 | ExitOnFailure(hr, "failed to get Wix4Group.Domain"); |
| 299 | wcsncpy_s(psgChild->wzDomain, pwzTempStr, MAX_DARWIN_COLUMN); | 299 | wcsncpy_s(psgChild->wzDomain, pwzTempStr, MAX_DARWIN_COLUMN); |
| 300 | ReleaseNullStr(pwzTempStr); | 300 | ReleaseNullStr(pwzTempStr); |
| @@ -412,8 +412,11 @@ LExit: | |||
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | /* **************************************************************** | 414 | /* **************************************************************** |
| 415 | ScaGroupExecute - Schedules group account creation or removal based on | 415 | ScaGroupExecute - Schedules group account creation or removal based on component state. |
| 416 | component state. | 416 | |
| 417 | Output: CustomData for CreateGroup - Name\tDomain\tComment\tAttributes\tScriptKey | ||
| 418 | CustomData for RollbackCreateGroup - ScriptKey\tName\tDomain\tComment\tRollbackAttributes | ||
| 419 | CustomData for RemoveGroup - Name\tDomain\tComment\tAttributes | ||
| 417 | ******************************************************************/ | 420 | ******************************************************************/ |
| 418 | HRESULT ScaGroupExecute( | 421 | HRESULT ScaGroupExecute( |
| 419 | __in SCA_GROUP *psgList | 422 | __in SCA_GROUP *psgList |
| @@ -455,8 +458,7 @@ HRESULT ScaGroupExecute( | |||
| 455 | // and removing groups. Note: MSDN says that it is safe to call these APIs from any | 458 | // and removing groups. Note: MSDN says that it is safe to call these APIs from any |
| 456 | // user, so we should be safe calling it during immediate mode. | 459 | // user, so we should be safe calling it during immediate mode. |
| 457 | 460 | ||
| 458 | LPCWSTR wzDomain = psg->wzDomain; | 461 | hr = GetDomainServerName(psg->wzDomain, &pwzServerName); |
| 459 | hr = GetDomainServerName(wzDomain, &pwzServerName); | ||
| 460 | 462 | ||
| 461 | er = ::NetLocalGroupGetInfo(pwzServerName, psg->wzName, 0, reinterpret_cast<LPBYTE*>(&pGroupInfo)); | 463 | er = ::NetLocalGroupGetInfo(pwzServerName, psg->wzName, 0, reinterpret_cast<LPBYTE*>(&pGroupInfo)); |
| 462 | if (NERR_Success == er) | 464 | if (NERR_Success == er) |
| @@ -471,7 +473,7 @@ HRESULT ScaGroupExecute( | |||
| 471 | { | 473 | { |
| 472 | geGroupExists = GROUP_EXISTS_INDETERMINATE; | 474 | geGroupExists = GROUP_EXISTS_INDETERMINATE; |
| 473 | hr = HRESULT_FROM_WIN32(er); | 475 | hr = HRESULT_FROM_WIN32(er); |
| 474 | WcaLog(LOGMSG_VERBOSE, "Failed to check existence of domain: %ls, group: %ls (error code 0x%x) - continuing", wzDomain, psg->wzName, hr); | 476 | WcaLog(LOGMSG_VERBOSE, "Failed to check existence of group: %ls\\%ls (error code 0x%x) - continuing", psg->wzDomain, psg->wzName, hr); |
| 475 | hr = S_OK; | 477 | hr = S_OK; |
| 476 | er = ERROR_SUCCESS; | 478 | er = ERROR_SUCCESS; |
| 477 | } | 479 | } |
| @@ -498,7 +500,7 @@ HRESULT ScaGroupExecute( | |||
| 498 | && !(SCAG_UPDATE_IF_EXISTS & psg->iAttributes)) | 500 | && !(SCAG_UPDATE_IF_EXISTS & psg->iAttributes)) |
| 499 | { | 501 | { |
| 500 | hr = HRESULT_FROM_WIN32(NERR_GroupExists); | 502 | hr = HRESULT_FROM_WIN32(NERR_GroupExists); |
| 501 | MessageExitOnFailure(hr, msierrGRPFailedGroupCreateExists, "Failed to create group: %ls because group already exists.", psg->wzName); | 503 | MessageExitOnFailure(hr, msierrGRPFailedGroupCreateExists, "Failed to create group: %ls\\%ls because group already exists.", psg->wzDomain, psg->wzName); |
| 502 | } | 504 | } |
| 503 | } | 505 | } |
| 504 | 506 | ||
| @@ -537,10 +539,19 @@ HRESULT ScaGroupExecute( | |||
| 537 | ExitOnFailure(hr, "Failed to add group name to rollback custom action data: %ls", psg->wzName); | 539 | ExitOnFailure(hr, "Failed to add group name to rollback custom action data: %ls", psg->wzName); |
| 538 | hr = WcaWriteStringToCaData(psg->wzDomain, &pwzRollbackData); | 540 | hr = WcaWriteStringToCaData(psg->wzDomain, &pwzRollbackData); |
| 539 | ExitOnFailure(hr, "Failed to add group domain to rollback custom action data: %ls", psg->wzDomain); | 541 | ExitOnFailure(hr, "Failed to add group domain to rollback custom action data: %ls", psg->wzDomain); |
| 542 | hr = WcaWriteStringToCaData(psg->wzComment, &pwzRollbackData); | ||
| 543 | ExitOnFailure(hr, "Failed to add group comment to rollback custom action data: %ls", psg->wzComment); | ||
| 540 | hr = WcaWriteIntegerToCaData(iRollbackUserAttributes, &pwzRollbackData); | 544 | hr = WcaWriteIntegerToCaData(iRollbackUserAttributes, &pwzRollbackData); |
| 541 | ExitOnFailure(hr, "failed to add group attributes to rollback custom action data for group: %ls", psg->wzKey); | 545 | ExitOnFailure(hr, "failed to add group rollback attributes to rollback custom action data: %i", iRollbackUserAttributes); |
| 542 | 546 | ||
| 543 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"CreateGroupRollback"), pwzRollbackData, COST_GROUP_DELETE); | 547 | if (*psg->wzDomain) |
| 548 | { | ||
| 549 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"CreateDomainGroupRollback"), pwzRollbackData, COST_GROUP_DELETE); | ||
| 550 | } | ||
| 551 | else | ||
| 552 | { | ||
| 553 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"CreateGroupRollback"), pwzRollbackData, COST_GROUP_DELETE); | ||
| 554 | } | ||
| 544 | ExitOnFailure(hr, "failed to schedule CreateGroupRollback"); | 555 | ExitOnFailure(hr, "failed to schedule CreateGroupRollback"); |
| 545 | } | 556 | } |
| 546 | else | 557 | else |
| @@ -571,11 +582,10 @@ HRESULT ScaGroupExecute( | |||
| 571 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); | 582 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); |
| 572 | ExitOnFailure(hr, "failed to add group attributes to custom action data for group: %ls", psg->wzKey); | 583 | ExitOnFailure(hr, "failed to add group attributes to custom action data for group: %ls", psg->wzKey); |
| 573 | 584 | ||
| 574 | // Schedule the removal because the group exists and we don't have any flags set | 585 | // Schedule the removal because the group exists and we don't have any flags set that say not to remove the group |
| 575 | // that say not to remove the group on uninstall. | 586 | // on uninstall. |
| 576 | // | 587 | // |
| 577 | // Note: We can't rollback the removal of a group which is why RemoveGroup is a commit | 588 | // Note: We can't rollback the removal of a group which is why RemoveGroup is a commit CustomAction. |
| 578 | // CustomAction. | ||
| 579 | if (psg->wzDomain && *psg->wzDomain) | 589 | if (psg->wzDomain && *psg->wzDomain) |
| 580 | { | 590 | { |
| 581 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveDomainGroup"), pwzActionData, COST_GROUP_DELETE); | 591 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveDomainGroup"), pwzActionData, COST_GROUP_DELETE); |
| @@ -631,15 +641,31 @@ LExit: | |||
| 631 | /* **************************************************************** | 641 | /* **************************************************************** |
| 632 | ScaGroupMembershipRemoveParentsExecute - Schedules group membership removal | 642 | ScaGroupMembershipRemoveParentsExecute - Schedules group membership removal |
| 633 | based on parent/child component state | 643 | based on parent/child component state |
| 644 | |||
| 645 | Output: deferred CustomActionData - | ||
| 646 | ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey | ||
| 647 | rollback CustomActionData - | ||
| 648 | ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey | ||
| 634 | ******************************************************************/ | 649 | ******************************************************************/ |
| 635 | HRESULT ScaGroupMembershipRemoveParentsExecute( | 650 | HRESULT ScaGroupMembershipRemoveParentsExecute( |
| 636 | __in SCA_GROUP* psg | 651 | __in SCA_GROUP* psg, |
| 652 | __inout DWORD &cScriptIndex | ||
| 637 | ) | 653 | ) |
| 638 | { | 654 | { |
| 639 | HRESULT hr = S_OK; | 655 | HRESULT hr = S_OK; |
| 640 | LPWSTR pwzActionData = NULL; | 656 | LPWSTR pwzActionData = NULL; |
| 657 | LPWSTR pwzBaseScriptKey = NULL; | ||
| 658 | LPWSTR pwzScriptKey = NULL; | ||
| 659 | SCA_GROUP* psgp = NULL; | ||
| 641 | 660 | ||
| 642 | for (SCA_GROUP* psgp = psg->psgParents; psgp; psgp = psgp->psgNext) | 661 | ++cScriptIndex; |
| 662 | // Get the base script key for this CustomAction. | ||
| 663 | hr = WcaCaScriptCreateKey(&pwzBaseScriptKey); | ||
| 664 | ExitOnFailure(hr, "Failed to get encoding key."); | ||
| 665 | hr = StrAllocFormatted(&pwzScriptKey, L"%ls_removemember_%u", pwzBaseScriptKey, cScriptIndex); | ||
| 666 | ExitOnFailure(hr, "Failed to create script key"); | ||
| 667 | |||
| 668 | for (psgp = psg->psgParents; psgp; psgp = psgp->psgNext) | ||
| 643 | { | 669 | { |
| 644 | Assert(psgp->wzName); | 670 | Assert(psgp->wzName); |
| 645 | if (WcaIsUninstalling(psg->isInstalled, psg->isAction) | 671 | if (WcaIsUninstalling(psg->isInstalled, psg->isAction) |
| @@ -655,18 +681,24 @@ HRESULT ScaGroupMembershipRemoveParentsExecute( | |||
| 655 | ExitOnFailure(hr, "Failed to add child group domain to custom action data: %ls", psg->wzDomain); | 681 | ExitOnFailure(hr, "Failed to add child group domain to custom action data: %ls", psg->wzDomain); |
| 656 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); | 682 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); |
| 657 | ExitOnFailure(hr, "Failed to add group attributes to custom action data: %i", psg->iAttributes); | 683 | ExitOnFailure(hr, "Failed to add group attributes to custom action data: %i", psg->iAttributes); |
| 684 | hr = WcaWriteStringToCaData(pwzScriptKey, &pwzActionData); | ||
| 685 | ExitOnFailure(hr, "Failed to add script key to custom action data: %i", pwzScriptKey); | ||
| 658 | 686 | ||
| 659 | if (psgp->wzDomain && *psgp->wzDomain) | 687 | if (psgp->wzDomain && *psgp->wzDomain) |
| 660 | { | 688 | { |
| 661 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveDomainGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_DELETE); | 689 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveDomainGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_DELETE); |
| 690 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveDomainGroupMembershipRollback"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | ||
| 662 | } | 691 | } |
| 663 | else | 692 | else |
| 664 | { | 693 | { |
| 665 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_DELETE); | 694 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_DELETE); |
| 695 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveGroupMembershipRollback"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | ||
| 666 | } | 696 | } |
| 667 | 697 | ||
| 668 | LExit: | 698 | LExit: |
| 669 | ReleaseNullStr(pwzActionData); | 699 | ReleaseNullStr(pwzActionData); |
| 700 | ReleaseNullStr(pwzBaseScriptKey); | ||
| 701 | ReleaseNullStr(pwzScriptKey); | ||
| 670 | if (hr != S_OK && !(psg->iAttributes & SCAG_NON_VITAL)) | 702 | if (hr != S_OK && !(psg->iAttributes & SCAG_NON_VITAL)) |
| 671 | { | 703 | { |
| 672 | return hr; | 704 | return hr; |
| @@ -677,16 +709,32 @@ HRESULT ScaGroupMembershipRemoveParentsExecute( | |||
| 677 | } | 709 | } |
| 678 | 710 | ||
| 679 | /* **************************************************************** | 711 | /* **************************************************************** |
| 680 | ScaGroupMembershipRemoveChildrenExecute - | 712 | ScaGroupMembershipRemoveChildrenExecute - |
| 713 | |||
| 714 | Output: deferred CustomActionData - | ||
| 715 | ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey | ||
| 716 | rollback CustomActionData - | ||
| 717 | ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey | ||
| 681 | ******************************************************************/ | 718 | ******************************************************************/ |
| 682 | HRESULT ScaGroupMembershipRemoveChildrenExecute( | 719 | HRESULT ScaGroupMembershipRemoveChildrenExecute( |
| 683 | __in SCA_GROUP* psg | 720 | __in SCA_GROUP* psg, |
| 721 | __inout DWORD &cScriptIndex | ||
| 684 | ) | 722 | ) |
| 685 | { | 723 | { |
| 686 | HRESULT hr = S_OK; | 724 | HRESULT hr = S_OK; |
| 687 | LPWSTR pwzActionData = NULL; | 725 | LPWSTR pwzActionData = NULL; |
| 726 | LPWSTR pwzBaseScriptKey = NULL; | ||
| 727 | LPWSTR pwzScriptKey = NULL; | ||
| 728 | SCA_GROUP* psgc = NULL; | ||
| 688 | 729 | ||
| 689 | for (SCA_GROUP* psgc = psg->psgChildren; psgc; psgc = psgc->psgNext) | 730 | ++cScriptIndex; |
| 731 | // Get the base script key for this CustomAction. | ||
| 732 | hr = WcaCaScriptCreateKey(&pwzBaseScriptKey); | ||
| 733 | ExitOnFailure(hr, "Failed to get encoding key."); | ||
| 734 | hr = StrAllocFormatted(&pwzScriptKey, L"%ls_removemember_%u", pwzBaseScriptKey, cScriptIndex); | ||
| 735 | ExitOnFailure(hr, "Failed to create script key"); | ||
| 736 | |||
| 737 | for (psgc = psg->psgChildren; psgc; psgc = psgc->psgNext) | ||
| 690 | { | 738 | { |
| 691 | Assert(psgc->wzName); | 739 | Assert(psgc->wzName); |
| 692 | if (WcaIsUninstalling(psg->isInstalled, psg->isAction) | 740 | if (WcaIsUninstalling(psg->isInstalled, psg->isAction) |
| @@ -702,17 +750,23 @@ HRESULT ScaGroupMembershipRemoveChildrenExecute( | |||
| 702 | ExitOnFailure(hr, "Failed to add child group domain to custom action data: %ls", psgc->wzDomain); | 750 | ExitOnFailure(hr, "Failed to add child group domain to custom action data: %ls", psgc->wzDomain); |
| 703 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); | 751 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); |
| 704 | ExitOnFailure(hr, "Failed to add group attributes to custom action data: %i", psg->iAttributes); | 752 | ExitOnFailure(hr, "Failed to add group attributes to custom action data: %i", psg->iAttributes); |
| 753 | hr = WcaWriteStringToCaData(pwzScriptKey, &pwzActionData); | ||
| 754 | ExitOnFailure(hr, "Failed to add script key to custom action data: %i", pwzScriptKey); | ||
| 705 | if (psg->wzDomain && *psg->wzDomain) | 755 | if (psg->wzDomain && *psg->wzDomain) |
| 706 | { | 756 | { |
| 707 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveDomainGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_DELETE); | 757 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveDomainGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_DELETE); |
| 758 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveDomainGroupMembershipRollback"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | ||
| 708 | } | 759 | } |
| 709 | else | 760 | else |
| 710 | { | 761 | { |
| 711 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_DELETE); | 762 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_DELETE); |
| 763 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"RemoveGroupMembershipRollback"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | ||
| 712 | } | 764 | } |
| 713 | 765 | ||
| 714 | LExit: | 766 | LExit: |
| 715 | ReleaseNullStr(pwzActionData); | 767 | ReleaseNullStr(pwzActionData); |
| 768 | ReleaseNullStr(pwzBaseScriptKey); | ||
| 769 | ReleaseNullStr(pwzScriptKey); | ||
| 716 | 770 | ||
| 717 | if (hr != S_OK && !(psg->iAttributes & SCAG_NON_VITAL)) | 771 | if (hr != S_OK && !(psg->iAttributes & SCAG_NON_VITAL)) |
| 718 | { | 772 | { |
| @@ -726,23 +780,29 @@ HRESULT ScaGroupMembershipRemoveChildrenExecute( | |||
| 726 | /* **************************************************************** | 780 | /* **************************************************************** |
| 727 | ScaGroupMembershipRemoveExecute - Schedules group membership removal | 781 | ScaGroupMembershipRemoveExecute - Schedules group membership removal |
| 728 | based on parent/child component state | 782 | based on parent/child component state |
| 783 | |||
| 784 | Output: deferred CustomActionData - | ||
| 785 | ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey | ||
| 786 | rollback CustomActionData - | ||
| 787 | ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey | ||
| 729 | ******************************************************************/ | 788 | ******************************************************************/ |
| 730 | HRESULT ScaGroupMembershipRemoveExecute( | 789 | HRESULT ScaGroupMembershipRemoveExecute( |
| 731 | __in SCA_GROUP* psgList | 790 | __in SCA_GROUP* psgList |
| 732 | ) | 791 | ) |
| 733 | { | 792 | { |
| 734 | HRESULT hr = S_OK; | 793 | HRESULT hr = S_OK; |
| 794 | static DWORD iScriptIndex = 0; | ||
| 735 | 795 | ||
| 736 | // Loop through all the users to be configured. | 796 | // Loop through all the users to be configured. |
| 737 | for (SCA_GROUP* psg = psgList; psg; psg = psg->psgNext) | 797 | for (SCA_GROUP* psg = psgList; psg; psg = psg->psgNext) |
| 738 | { | 798 | { |
| 739 | Assert(psg->wzName); | 799 | Assert(psg->wzName); |
| 740 | // first we loop through the Parents | 800 | // first we loop through the Parents |
| 741 | hr = ScaGroupMembershipRemoveParentsExecute(psg); | 801 | hr = ScaGroupMembershipRemoveParentsExecute(psg, iScriptIndex); |
| 742 | ExitOnFailure(hr, "Failed to remove parent membership for vital group: %ls", psg->wzKey); | 802 | ExitOnFailure(hr, "Failed to remove parent membership for vital group: %ls", psg->wzKey); |
| 743 | 803 | ||
| 744 | // then through the Children | 804 | // then through the Children |
| 745 | hr = ScaGroupMembershipRemoveChildrenExecute(psg); | 805 | hr = ScaGroupMembershipRemoveChildrenExecute(psg, iScriptIndex); |
| 746 | ExitOnFailure(hr, "Failed to remove child membership for vital group: %ls", psg->wzKey); | 806 | ExitOnFailure(hr, "Failed to remove child membership for vital group: %ls", psg->wzKey); |
| 747 | } | 807 | } |
| 748 | 808 | ||
| @@ -755,13 +815,24 @@ ScaGroupMembershipAddParentsExecute - Schedules group membership removal | |||
| 755 | based on parent/child component state | 815 | based on parent/child component state |
| 756 | ******************************************************************/ | 816 | ******************************************************************/ |
| 757 | HRESULT ScaGroupMembershipAddParentsExecute( | 817 | HRESULT ScaGroupMembershipAddParentsExecute( |
| 758 | __in SCA_GROUP* psg | 818 | __in SCA_GROUP* psg, |
| 819 | __inout DWORD &cScriptIndex | ||
| 759 | ) | 820 | ) |
| 760 | { | 821 | { |
| 761 | HRESULT hr = S_OK; | 822 | HRESULT hr = S_OK; |
| 762 | LPWSTR pwzActionData = NULL; | 823 | LPWSTR pwzActionData = NULL; |
| 824 | LPWSTR pwzBaseScriptKey = NULL; | ||
| 825 | LPWSTR pwzScriptKey = NULL; | ||
| 826 | SCA_GROUP* psgp = NULL; | ||
| 827 | |||
| 828 | ++cScriptIndex; | ||
| 829 | // Get the base script key for this CustomAction. | ||
| 830 | hr = WcaCaScriptCreateKey(&pwzBaseScriptKey); | ||
| 831 | ExitOnFailure(hr, "Failed to get encoding key."); | ||
| 832 | hr = StrAllocFormatted(&pwzScriptKey, L"%ls_addmember_%u", pwzBaseScriptKey, cScriptIndex); | ||
| 833 | ExitOnFailure(hr, "Failed to create script key"); | ||
| 763 | 834 | ||
| 764 | for (SCA_GROUP* psgp = psg->psgParents; psgp; psgp = psgp->psgNext) | 835 | for (psgp = psg->psgParents; psgp; psgp = psgp->psgNext) |
| 765 | { | 836 | { |
| 766 | Assert(psgp->wzName); | 837 | Assert(psgp->wzName); |
| 767 | if (WcaIsInstalling(psg->isInstalled, psg->isAction) | 838 | if (WcaIsInstalling(psg->isInstalled, psg->isAction) |
| @@ -777,17 +848,23 @@ HRESULT ScaGroupMembershipAddParentsExecute( | |||
| 777 | ExitOnFailure(hr, "Failed to add child group domain to custom action data: %ls", psg->wzDomain); | 848 | ExitOnFailure(hr, "Failed to add child group domain to custom action data: %ls", psg->wzDomain); |
| 778 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); | 849 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); |
| 779 | ExitOnFailure(hr, "Failed to add group attributes to custom action data: %i", psg->iAttributes); | 850 | ExitOnFailure(hr, "Failed to add group attributes to custom action data: %i", psg->iAttributes); |
| 851 | hr = WcaWriteStringToCaData(pwzScriptKey, &pwzActionData); | ||
| 852 | ExitOnFailure(hr, "Failed to add script key to custom action data: %i", pwzScriptKey); | ||
| 780 | if (psgp->wzDomain&&* psgp->wzDomain) | 853 | if (psgp->wzDomain&&* psgp->wzDomain) |
| 781 | { | 854 | { |
| 782 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddDomainGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | 855 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddDomainGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); |
| 856 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddDomainGroupMembershipRollback"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | ||
| 783 | } | 857 | } |
| 784 | else | 858 | else |
| 785 | { | 859 | { |
| 786 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | 860 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); |
| 861 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddGroupMembershipRollback"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | ||
| 787 | } | 862 | } |
| 788 | 863 | ||
| 789 | LExit: | 864 | LExit: |
| 790 | ReleaseNullStr(pwzActionData); | 865 | ReleaseNullStr(pwzActionData); |
| 866 | ReleaseNullStr(pwzBaseScriptKey); | ||
| 867 | ReleaseNullStr(pwzScriptKey); | ||
| 791 | 868 | ||
| 792 | if (hr != S_OK && !(psg->iAttributes & SCAG_NON_VITAL)) | 869 | if (hr != S_OK && !(psg->iAttributes & SCAG_NON_VITAL)) |
| 793 | { | 870 | { |
| @@ -801,16 +878,32 @@ HRESULT ScaGroupMembershipAddParentsExecute( | |||
| 801 | /* **************************************************************** | 878 | /* **************************************************************** |
| 802 | ScaGroupMembershipAddChildrenExecute - Schedules group membership removal | 879 | ScaGroupMembershipAddChildrenExecute - Schedules group membership removal |
| 803 | based on parent/child component state | 880 | based on parent/child component state |
| 881 | |||
| 882 | Output: deferred CustomActionData - | ||
| 883 | ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey | ||
| 884 | rollback CustomActionData - | ||
| 885 | ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey | ||
| 804 | ******************************************************************/ | 886 | ******************************************************************/ |
| 805 | HRESULT ScaGroupMembershipAddChildrenExecute( | 887 | HRESULT ScaGroupMembershipAddChildrenExecute( |
| 806 | __in SCA_GROUP* psg | 888 | __in SCA_GROUP* psg, |
| 889 | __inout DWORD &cScriptIndex | ||
| 807 | ) | 890 | ) |
| 808 | { | 891 | { |
| 809 | HRESULT hr = S_OK; | 892 | HRESULT hr = S_OK; |
| 810 | LPWSTR pwzActionData = NULL; | 893 | LPWSTR pwzActionData = NULL; |
| 894 | LPWSTR pwzBaseScriptKey = NULL; | ||
| 895 | LPWSTR pwzScriptKey = NULL; | ||
| 896 | SCA_GROUP* psgc = NULL; | ||
| 897 | |||
| 898 | ++cScriptIndex; | ||
| 899 | // Get the base script key for this CustomAction. | ||
| 900 | hr = WcaCaScriptCreateKey(&pwzBaseScriptKey); | ||
| 901 | ExitOnFailure(hr, "Failed to get encoding key."); | ||
| 902 | hr = StrAllocFormatted(&pwzScriptKey, L"%ls_addmember_%u", pwzBaseScriptKey, cScriptIndex); | ||
| 903 | ExitOnFailure(hr, "Failed to create script key"); | ||
| 811 | 904 | ||
| 812 | // then through the Children | 905 | // then through the Children |
| 813 | for (SCA_GROUP* psgc = psg->psgChildren; psgc; psgc = psgc->psgNext) | 906 | for (psgc = psg->psgChildren; psgc; psgc = psgc->psgNext) |
| 814 | { | 907 | { |
| 815 | Assert(psgc->wzName); | 908 | Assert(psgc->wzName); |
| 816 | if (WcaIsInstalling(psg->isInstalled, psg->isAction) | 909 | if (WcaIsInstalling(psg->isInstalled, psg->isAction) |
| @@ -826,17 +919,24 @@ HRESULT ScaGroupMembershipAddChildrenExecute( | |||
| 826 | ExitOnFailure(hr, "Failed to add parent group domain to custom action data: %ls", psgc->wzDomain); | 919 | ExitOnFailure(hr, "Failed to add parent group domain to custom action data: %ls", psgc->wzDomain); |
| 827 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); | 920 | hr = WcaWriteIntegerToCaData(psg->iAttributes, &pwzActionData); |
| 828 | ExitOnFailure(hr, "Failed to add group attributes to custom action data: %i", psg->iAttributes); | 921 | ExitOnFailure(hr, "Failed to add group attributes to custom action data: %i", psg->iAttributes); |
| 922 | hr = WcaWriteStringToCaData(pwzScriptKey, &pwzActionData); | ||
| 923 | ExitOnFailure(hr, "Failed to add script key to custom action data: %i", pwzScriptKey); | ||
| 829 | if (psg->wzDomain && *psg->wzDomain) | 924 | if (psg->wzDomain && *psg->wzDomain) |
| 830 | { | 925 | { |
| 831 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddDomainGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | 926 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddDomainGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); |
| 927 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddDomainGroupMembershipRollback"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | ||
| 832 | } | 928 | } |
| 833 | else | 929 | else |
| 834 | { | 930 | { |
| 835 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | 931 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddGroupMembership"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); |
| 932 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION6(L"AddGroupMembershipRollback"), pwzActionData, COST_GROUPMEMBERSHIP_ADD); | ||
| 836 | } | 933 | } |
| 837 | 934 | ||
| 838 | LExit: | 935 | LExit: |
| 839 | ReleaseNullStr(pwzActionData); | 936 | ReleaseNullStr(pwzActionData); |
| 937 | ReleaseNullStr(pwzBaseScriptKey); | ||
| 938 | ReleaseNullStr(pwzScriptKey); | ||
| 939 | |||
| 840 | if (hr != S_OK && !(psg->iAttributes & SCAG_NON_VITAL)) | 940 | if (hr != S_OK && !(psg->iAttributes & SCAG_NON_VITAL)) |
| 841 | { | 941 | { |
| 842 | return hr; | 942 | return hr; |
| @@ -855,17 +955,18 @@ HRESULT ScaGroupMembershipAddExecute( | |||
| 855 | ) | 955 | ) |
| 856 | { | 956 | { |
| 857 | HRESULT hr = S_OK; | 957 | HRESULT hr = S_OK; |
| 958 | static DWORD iScriptIndex = 0; | ||
| 858 | 959 | ||
| 859 | // Loop through all the users to be configured. | 960 | // Loop through all the users to be configured. |
| 860 | for (SCA_GROUP* psg = psgList; psg; psg = psg->psgNext) | 961 | for (SCA_GROUP* psg = psgList; psg; psg = psg->psgNext) |
| 861 | { | 962 | { |
| 862 | Assert(psg->wzName); | 963 | Assert(psg->wzName); |
| 863 | // first we loop through the Parents | 964 | // first we loop through the Parents |
| 864 | hr = ScaGroupMembershipAddParentsExecute(psg); | 965 | hr = ScaGroupMembershipAddParentsExecute(psg, iScriptIndex); |
| 865 | ExitOnFailure(hr, "Failed to add parent membership for vital group: %ls", psg->wzKey); | 966 | ExitOnFailure(hr, "Failed to add parent membership for vital group: %ls", psg->wzKey); |
| 866 | 967 | ||
| 867 | // then through the Children | 968 | // then through the Children |
| 868 | hr = ScaGroupMembershipAddChildrenExecute(psg); | 969 | hr = ScaGroupMembershipAddChildrenExecute(psg, iScriptIndex); |
| 869 | ExitOnFailure(hr, "Failed to add child membership for vital group: %ls", psg->wzKey); | 970 | ExitOnFailure(hr, "Failed to add child membership for vital group: %ls", psg->wzKey); |
| 870 | } | 971 | } |
| 871 | 972 | ||
diff --git a/src/ext/Util/ca/scasched.cpp b/src/ext/Util/ca/scasched.cpp index cef7fecb..d7378b13 100644 --- a/src/ext/Util/ca/scasched.cpp +++ b/src/ext/Util/ca/scasched.cpp | |||
| @@ -134,7 +134,7 @@ extern "C" UINT __stdcall ConfigureGroups( | |||
| 134 | __in MSIHANDLE hInstall | 134 | __in MSIHANDLE hInstall |
| 135 | ) | 135 | ) |
| 136 | { | 136 | { |
| 137 | //AssertSz(0, "Debug ConfigureGroups"); | 137 | AssertSz(0, "Debug ConfigureGroups"); |
| 138 | 138 | ||
| 139 | HRESULT hr = S_OK; | 139 | HRESULT hr = S_OK; |
| 140 | UINT er = ERROR_SUCCESS; | 140 | UINT er = ERROR_SUCCESS; |
diff --git a/src/test/burn/WixTestTools/RuntimeFactAttribute.cs b/src/test/burn/WixTestTools/RuntimeFactAttribute.cs index 573a9de2..76004f26 100644 --- a/src/test/burn/WixTestTools/RuntimeFactAttribute.cs +++ b/src/test/burn/WixTestTools/RuntimeFactAttribute.cs | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | namespace WixTestTools | 3 | namespace WixTestTools |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.DirectoryServices.ActiveDirectory; | ||
| 6 | using System.Security.Principal; | 7 | using System.Security.Principal; |
| 7 | using WixInternal.TestSupport.XunitExtensions; | 8 | using WixInternal.TestSupport.XunitExtensions; |
| 8 | using System.Runtime.InteropServices; | 9 | using System.Runtime.InteropServices; |
| @@ -10,10 +11,13 @@ namespace WixTestTools | |||
| 10 | public class RuntimeFactAttribute : SkippableFactAttribute | 11 | public class RuntimeFactAttribute : SkippableFactAttribute |
| 11 | { | 12 | { |
| 12 | const string RequiredEnvironmentVariableName = "RuntimeTestsEnabled"; | 13 | const string RequiredEnvironmentVariableName = "RuntimeTestsEnabled"; |
| 14 | const string RequiredDomainEnvironmentVariableName = "RuntimeDomainTestsEnabled"; | ||
| 13 | 15 | ||
| 14 | public static bool RuntimeTestsEnabled { get; } | 16 | public static bool RuntimeTestsEnabled { get; } |
| 17 | public static bool RuntimeDomainTestsEnabled { get; } | ||
| 15 | public static bool RunningAsAdministrator { get; } | 18 | public static bool RunningAsAdministrator { get; } |
| 16 | public static bool RunningOnWindowsServer { get; } | 19 | public static bool RunningOnWindowsServer { get; } |
| 20 | public static bool RunningInDomain { get; } | ||
| 17 | 21 | ||
| 18 | [DllImport("shlwapi.dll", SetLastError = true, EntryPoint = "#437")] | 22 | [DllImport("shlwapi.dll", SetLastError = true, EntryPoint = "#437")] |
| 19 | private static extern bool IsOS(int os); | 23 | private static extern bool IsOS(int os); |
| @@ -23,7 +27,6 @@ namespace WixTestTools | |||
| 23 | return IsOS(OS_ANYSERVER); | 27 | return IsOS(OS_ANYSERVER); |
| 24 | } | 28 | } |
| 25 | 29 | ||
| 26 | |||
| 27 | static RuntimeFactAttribute() | 30 | static RuntimeFactAttribute() |
| 28 | { | 31 | { |
| 29 | using var identity = WindowsIdentity.GetCurrent(); | 32 | using var identity = WindowsIdentity.GetCurrent(); |
| @@ -33,6 +36,33 @@ namespace WixTestTools | |||
| 33 | var testsEnabledString = Environment.GetEnvironmentVariable(RequiredEnvironmentVariableName); | 36 | var testsEnabledString = Environment.GetEnvironmentVariable(RequiredEnvironmentVariableName); |
| 34 | RuntimeTestsEnabled = Boolean.TryParse(testsEnabledString, out var testsEnabled) && testsEnabled; | 37 | RuntimeTestsEnabled = Boolean.TryParse(testsEnabledString, out var testsEnabled) && testsEnabled; |
| 35 | 38 | ||
| 39 | RunningInDomain = false; | ||
| 40 | try | ||
| 41 | { | ||
| 42 | RunningInDomain = !String.IsNullOrEmpty(System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name); | ||
| 43 | } | ||
| 44 | catch (ActiveDirectoryObjectNotFoundException) { } | ||
| 45 | |||
| 46 | var domainTestsEnabledString = Environment.GetEnvironmentVariable(RequiredDomainEnvironmentVariableName); | ||
| 47 | RuntimeDomainTestsEnabled = Boolean.TryParse(domainTestsEnabledString, out var domainTestsEnabled) && domainTestsEnabled; | ||
| 48 | } | ||
| 49 | |||
| 50 | private bool _domainRequired; | ||
| 51 | public bool DomainRequired | ||
| 52 | { | ||
| 53 | get | ||
| 54 | { | ||
| 55 | return _domainRequired; | ||
| 56 | } | ||
| 57 | set | ||
| 58 | { | ||
| 59 | _domainRequired = value; | ||
| 60 | if (_domainRequired && String.IsNullOrEmpty(this.Skip) && (!RunningInDomain || !RuntimeDomainTestsEnabled)) | ||
| 61 | { | ||
| 62 | this.Skip = $"These tests require the test host to be running as a domain member ({(RunningInDomain ? "passed" : "failed")}). These tests affect both MACHINE AND DOMAIN state. To accept the consequences, set the {RequiredDomainEnvironmentVariableName} environment variable to true ({(RuntimeDomainTestsEnabled ? "passed" : "failed")})."; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 36 | RunningOnWindowsServer = IsWindowsServer(); | 66 | RunningOnWindowsServer = IsWindowsServer(); |
| 37 | } | 67 | } |
| 38 | 68 | ||
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductA/product.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductA/product.wxs index e3c143e6..f7f60fdb 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductA/product.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductA/product.wxs | |||
| @@ -7,19 +7,18 @@ | |||
| 7 | <ComponentRef Id="Component1" /> | 7 | <ComponentRef Id="Component1" /> |
| 8 | </ComponentGroup> | 8 | </ComponentGroup> |
| 9 | 9 | ||
| 10 | <Property Id="TEMPDOMAIN" Secure="yes" /> | 10 | <Property Id="TESTDOMAIN" Secure="yes" /> |
| 11 | <Property Id="TEMPGROUPNAME" Secure="yes" /> | ||
| 12 | </Fragment> | 11 | </Fragment> |
| 13 | 12 | ||
| 14 | <Fragment> | 13 | <Fragment> |
| 15 | <Component Id="Component1" Guid="09624A9A-4BBC-4126-BBF9-0713C5217DB1" Directory="INSTALLFOLDER"> | 14 | <Component Id="Component1" Guid="09624A9A-4BBC-4126-BBF9-0713C5217DB1" Directory="INSTALLFOLDER"> |
| 16 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | 15 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> |
| 17 | 16 | ||
| 18 | <util:Group Id="TEST_GROUP1" Name="testName1" Comment="Group1" CreateGroup="yes" RemoveOnUninstall="yes" /> | 17 | <util:Group Id="TEST_GROUP1" Name="testName1" Domain="[TESTDOMAIN]" Comment="Group1" CreateGroup="yes" RemoveOnUninstall="yes" /> |
| 19 | 18 | ||
| 20 | <util:Group Id="TEST_GROUP2" Name="testName2" Comment="Group2" RemoveOnUninstall="no" UpdateIfExists="yes" /> | 19 | <util:Group Id="TEST_GROUP2" Name="testName2" Domain="[TESTDOMAIN]" Comment="Group2" RemoveOnUninstall="no" UpdateIfExists="yes" /> |
| 21 | 20 | ||
| 22 | <util:Group Id="TEST_GROUP3" Name="testName3" Comment="Group3" CreateGroup="no" /> | 21 | <util:Group Id="TEST_GROUP3" Name="testName3" Domain="[TESTDOMAIN]" Comment="Group3" CreateGroup="no" /> |
| 23 | </Component> | 22 | </Component> |
| 24 | </Fragment> | 23 | </Fragment> |
| 25 | </Wix> | 24 | </Wix> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductAddCommentToExistingGroup/product.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductAddCommentToExistingGroup/product.wxs index e0170746..6c9d3be3 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductAddCommentToExistingGroup/product.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductAddCommentToExistingGroup/product.wxs | |||
| @@ -6,18 +6,15 @@ | |||
| 6 | <ComponentGroup Id="ProductComponents"> | 6 | <ComponentGroup Id="ProductComponents"> |
| 7 | <ComponentRef Id="Component1" /> | 7 | <ComponentRef Id="Component1" /> |
| 8 | </ComponentGroup> | 8 | </ComponentGroup> |
| 9 | |||
| 10 | <Property Id="TESTDOMAIN" Secure="yes" /> | ||
| 9 | </Fragment> | 11 | </Fragment> |
| 10 | 12 | ||
| 11 | <Fragment> | 13 | <Fragment> |
| 12 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | 14 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> |
| 13 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | 15 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> |
| 14 | 16 | ||
| 15 | <util:Group Id="TEST_GROUP1" | 17 | <util:Group Id="TEST_GROUP1" Name="testName1" Domain="[TESTDOMAIN]" CreateGroup="yes" UpdateIfExists="yes" RemoveOnUninstall="yes" Comment="testComment1"/> |
| 16 | Name="testName1" | ||
| 17 | CreateGroup="yes" | ||
| 18 | UpdateIfExists="yes" | ||
| 19 | RemoveOnUninstall="yes" | ||
| 20 | Comment="testComment1"/> | ||
| 21 | </Component> | 18 | </Component> |
| 22 | </Fragment> | 19 | </Fragment> |
| 23 | </Wix> | 20 | </Wix> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductCommentDelete/product.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductCommentDelete/product.wxs index d1824890..a34a276b 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductCommentDelete/product.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductCommentDelete/product.wxs | |||
| @@ -6,13 +6,15 @@ | |||
| 6 | <ComponentGroup Id="ProductComponents"> | 6 | <ComponentGroup Id="ProductComponents"> |
| 7 | <ComponentRef Id="Component1" /> | 7 | <ComponentRef Id="Component1" /> |
| 8 | </ComponentGroup> | 8 | </ComponentGroup> |
| 9 | |||
| 10 | <Property Id="TESTDOMAIN" Secure="yes" /> | ||
| 9 | </Fragment> | 11 | </Fragment> |
| 10 | 12 | ||
| 11 | <Fragment> | 13 | <Fragment> |
| 12 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | 14 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> |
| 13 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | 15 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> |
| 14 | 16 | ||
| 15 | <util:Group Id="TEST_GROUP1" Name="testName1" UpdateIfExists="yes" RemoveOnUninstall="yes" RemoveComment="yes"/> | 17 | <util:Group Id="TEST_GROUP1" Name="testName1" Domain="[TESTDOMAIN]" UpdateIfExists="yes" RemoveOnUninstall="yes" RemoveComment="yes"/> |
| 16 | </Component> | 18 | </Component> |
| 17 | </Fragment> | 19 | </Fragment> |
| 18 | </Wix> | 20 | </Wix> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductCommentFail/product_fail.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductCommentFail/product_fail.wxs index 4e70717f..79396882 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductCommentFail/product_fail.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductCommentFail/product_fail.wxs | |||
| @@ -10,13 +10,15 @@ | |||
| 10 | <InstallExecuteSequence> | 10 | <InstallExecuteSequence> |
| 11 | <Custom Action="CaFail" After="Wix6ConfigureGroups_X86" /> | 11 | <Custom Action="CaFail" After="Wix6ConfigureGroups_X86" /> |
| 12 | </InstallExecuteSequence> | 12 | </InstallExecuteSequence> |
| 13 | |||
| 14 | <Property Id="TESTDOMAIN" Secure="yes" /> | ||
| 13 | </Fragment> | 15 | </Fragment> |
| 14 | 16 | ||
| 15 | <Fragment> | 17 | <Fragment> |
| 16 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | 18 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> |
| 17 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | 19 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> |
| 18 | 20 | ||
| 19 | <util:Group Id="TEST_GROUP1" Name="testName1" CreateGroup="yes" RemoveOnUninstall="yes" Comment="testComment1"/> | 21 | <util:Group Id="TEST_GROUP1" Name="testName1" Domain="[TESTDOMAIN]" CreateGroup="yes" RemoveOnUninstall="yes" Comment="testComment1"/> |
| 20 | </Component> | 22 | </Component> |
| 21 | </Fragment> | 23 | </Fragment> |
| 22 | </Wix> | 24 | </Wix> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductFail/product_fail.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductFail/product_fail.wxs index 3013e5a0..148f26ca 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductFail/product_fail.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductFail/product_fail.wxs | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | <InstallExecuteSequence> | 13 | <InstallExecuteSequence> |
| 14 | <Custom Action="CaFail" After="Wix6ConfigureGroups_X86" /> | 14 | <Custom Action="CaFail" After="Wix6ConfigureGroups_X86" /> |
| 15 | </InstallExecuteSequence> | 15 | </InstallExecuteSequence> |
| 16 | |||
| 17 | <Property Id="TESTDOMAIN" Secure="yes" /> | ||
| 16 | </Fragment> | 18 | </Fragment> |
| 17 | 19 | ||
| 18 | <Fragment> | 20 | <Fragment> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductFailIfExists/FailIfExists.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductFailIfExists/FailIfExists.wxs index 00f8e12d..e7acb5e0 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductFailIfExists/FailIfExists.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductFailIfExists/FailIfExists.wxs | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | <ComponentGroup Id="ProductComponents"> | 6 | <ComponentGroup Id="ProductComponents"> |
| 7 | <ComponentRef Id="Component1" /> | 7 | <ComponentRef Id="Component1" /> |
| 8 | </ComponentGroup> | 8 | </ComponentGroup> |
| 9 | |||
| 10 | <Property Id="TESTDOMAIN" Secure="yes" /> | ||
| 9 | </Fragment> | 11 | </Fragment> |
| 10 | 12 | ||
| 11 | <Fragment> | 13 | <Fragment> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductNestedGroups/product.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductNestedGroups/product.wxs index c27eb27a..f513e7c6 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductNestedGroups/product.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductNestedGroups/product.wxs | |||
| @@ -7,13 +7,14 @@ | |||
| 7 | <ComponentRef Id="Component1" /> | 7 | <ComponentRef Id="Component1" /> |
| 8 | </ComponentGroup> | 8 | </ComponentGroup> |
| 9 | 9 | ||
| 10 | <Property Id="TEMPDOMAIN" Secure="yes" Value="TESTDOMAIN" /> | 10 | <Property Id="TESTDOMAIN" Secure="yes" /> |
| 11 | </Fragment> | 11 | </Fragment> |
| 12 | 12 | ||
| 13 | <Fragment> | 13 | <Fragment> |
| 14 | <util:Group Id="AUTH_USERS" Name="Authenticated Users" Domain="[TEMPDOMAIN]" > | 14 | <util:Group Id="DOMAIN_USERS" Name="Domain Users" Domain="[TESTDOMAIN]" > |
| 15 | <util:GroupRef Id="TEST_GROUP1" /> | 15 | <util:GroupRef Id="TEST_GROUP1" /> |
| 16 | <util:GroupRef Id="TEST_GROUP2" /> | 16 | <util:GroupRef Id="TEST_GROUP2" /> |
| 17 | <util:GroupRef Id="TEST_GROUP3" /> | ||
| 17 | </util:Group> | 18 | </util:Group> |
| 18 | <util:Group Id="EVERYONE" Name="Everyone" > | 19 | <util:Group Id="EVERYONE" Name="Everyone" > |
| 19 | <util:GroupRef Id="TEST_GROUP1" /> | 20 | <util:GroupRef Id="TEST_GROUP1" /> |
| @@ -25,6 +26,8 @@ | |||
| 25 | <util:Group Id="TEST_GROUP1" Name="testName1" Comment="Group1" CreateGroup="yes" RemoveOnUninstall="yes" /> | 26 | <util:Group Id="TEST_GROUP1" Name="testName1" Comment="Group1" CreateGroup="yes" RemoveOnUninstall="yes" /> |
| 26 | 27 | ||
| 27 | <util:Group Id="TEST_GROUP2" Name="testName2" Comment="Group2" RemoveOnUninstall="no" UpdateIfExists="yes" /> | 28 | <util:Group Id="TEST_GROUP2" Name="testName2" Comment="Group2" RemoveOnUninstall="no" UpdateIfExists="yes" /> |
| 29 | |||
| 30 | <util:Group Id="TEST_GROUP3" Name="testName3" Domain="[TESTDOMAIN]" Comment="Group3" RemoveOnUninstall="no" UpdateIfExists="yes" /> | ||
| 28 | </Component> | 31 | </Component> |
| 29 | </Fragment> | 32 | </Fragment> |
| 30 | </Wix> | 33 | </Wix> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductNewGroupWithComment/product.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductNewGroupWithComment/product.wxs index 2d012b23..2305a80b 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductNewGroupWithComment/product.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductNewGroupWithComment/product.wxs | |||
| @@ -6,18 +6,15 @@ | |||
| 6 | <ComponentGroup Id="ProductComponents"> | 6 | <ComponentGroup Id="ProductComponents"> |
| 7 | <ComponentRef Id="Component1" /> | 7 | <ComponentRef Id="Component1" /> |
| 8 | </ComponentGroup> | 8 | </ComponentGroup> |
| 9 | |||
| 10 | <Property Id="TESTDOMAIN" Secure="yes" /> | ||
| 9 | </Fragment> | 11 | </Fragment> |
| 10 | 12 | ||
| 11 | <Fragment> | 13 | <Fragment> |
| 12 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | 14 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> |
| 13 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | 15 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> |
| 14 | <util:Group | 16 | <util:Group |
| 15 | Id="TEST_GROUP1" | 17 | Id="TEST_GROUP1" Name="testName1" CreateGroup="yes" UpdateIfExists="yes" RemoveOnUninstall="yes" Comment="testComment1" /> |
| 16 | Name="testName1" | ||
| 17 | CreateGroup="yes" | ||
| 18 | UpdateIfExists="yes" | ||
| 19 | RemoveOnUninstall="yes" | ||
| 20 | Comment="testComment1" /> | ||
| 21 | </Component> | 18 | </Component> |
| 22 | </Fragment> | 19 | </Fragment> |
| 23 | </Wix> | 20 | </Wix> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductNonVitalGroup/NonVitalUserGroup.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductNonVitalGroup/NonVitalUserGroup.wxs index a834c76b..4922fcef 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductNonVitalGroup/NonVitalUserGroup.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductNonVitalGroup/NonVitalUserGroup.wxs | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | <ComponentGroup Id="ProductComponents"> | 6 | <ComponentGroup Id="ProductComponents"> |
| 7 | <ComponentRef Id="Component1" /> | 7 | <ComponentRef Id="Component1" /> |
| 8 | </ComponentGroup> | 8 | </ComponentGroup> |
| 9 | |||
| 10 | <Property Id="TESTDOMAIN" Secure="yes" /> | ||
| 9 | </Fragment> | 11 | </Fragment> |
| 10 | 12 | ||
| 11 | <Fragment> | 13 | <Fragment> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductRestrictedDomain/RestrictedDomain.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductRestrictedDomain/RestrictedDomain.wxs index edb3387c..04a1ac4e 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductRestrictedDomain/RestrictedDomain.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductRestrictedDomain/RestrictedDomain.wxs | |||
| @@ -7,14 +7,14 @@ | |||
| 7 | <ComponentRef Id="Component1" /> | 7 | <ComponentRef Id="Component1" /> |
| 8 | </ComponentGroup> | 8 | </ComponentGroup> |
| 9 | 9 | ||
| 10 | <Property Id="TEMPDOMAIN" Secure="yes" /> | 10 | <Property Id="TESTDOMAIN" Secure="yes" /> |
| 11 | </Fragment> | 11 | </Fragment> |
| 12 | 12 | ||
| 13 | <Fragment> | 13 | <Fragment> |
| 14 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | 14 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> |
| 15 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | 15 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> |
| 16 | 16 | ||
| 17 | <util:Group Id="TEST_GROUP_test" Name="testName1" Domain="[TEMPDOMAIN]" /> | 17 | <util:Group Id="TEST_GROUP_test" Name="testName1" Domain="[TESTDOMAIN]" /> |
| 18 | </Component> | 18 | </Component> |
| 19 | </Fragment> | 19 | </Fragment> |
| 20 | </Wix> | 20 | </Wix> |
diff --git a/src/test/msi/TestData/UtilExtensionGroupTests/ProductWithCommandLineParameters/ProductWithCommandLineParameters.wxs b/src/test/msi/TestData/UtilExtensionGroupTests/ProductWithCommandLineParameters/ProductWithCommandLineParameters.wxs index 059ecee8..36d10aa3 100644 --- a/src/test/msi/TestData/UtilExtensionGroupTests/ProductWithCommandLineParameters/ProductWithCommandLineParameters.wxs +++ b/src/test/msi/TestData/UtilExtensionGroupTests/ProductWithCommandLineParameters/ProductWithCommandLineParameters.wxs | |||
| @@ -4,16 +4,13 @@ | |||
| 4 | <ComponentGroup Id="ProductComponents"> | 4 | <ComponentGroup Id="ProductComponents"> |
| 5 | <ComponentRef Id="Component1" /> | 5 | <ComponentRef Id="Component1" /> |
| 6 | </ComponentGroup> | 6 | </ComponentGroup> |
| 7 | |||
| 8 | <Property Id="TESTDOMAIN" Secure="yes" /> | ||
| 7 | </Fragment> | 9 | </Fragment> |
| 8 | 10 | ||
| 9 | <Fragment> | 11 | <Fragment> |
| 10 | <Component Id="Component1" | 12 | <Component Id="Component1" Guid="1FDC6C4D-7741-4BF1-A4F0-4231879CEC45" Directory="INSTALLFOLDER"> |
| 11 | Guid="1FDC6C4D-7741-4BF1-A4F0-4231879CEC45" | 13 | <util:Group Id="TEST_GROUP1" Name="[TESTPARAMETER1]" Domain="[TESTDOMAIN]" CreateGroup="yes" RemoveOnUninstall="yes" /> |
| 12 | Directory="INSTALLFOLDER"> | ||
| 13 | <util:Group Id="TEST_GROUP1" | ||
| 14 | Name="[TESTPARAMETER1]" | ||
| 15 | CreateGroup="yes" | ||
| 16 | RemoveOnUninstall="yes" /> | ||
| 17 | </Component> | 14 | </Component> |
| 18 | </Fragment> | 15 | </Fragment> |
| 19 | </Wix> | 16 | </Wix> |
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs index d7cf3168..cee357a6 100644 --- a/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs +++ b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs | |||
| @@ -11,9 +11,10 @@ namespace WixToolsetTest.MsiE2E | |||
| 11 | { | 11 | { |
| 12 | public UtilExtensionGroupTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } | 12 | public UtilExtensionGroupTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } |
| 13 | 13 | ||
| 14 | #region Non Domain | ||
| 14 | // Verify that the users specified in the authoring are created as expected. | 15 | // Verify that the users specified in the authoring are created as expected. |
| 15 | [RuntimeFact] | 16 | [RuntimeFact] |
| 16 | public void CanInstallAndUninstallGroups() | 17 | public void CanInstallAndUninstallNonDomainGroups() |
| 17 | { | 18 | { |
| 18 | UserGroupVerifier.CreateLocalGroup("testName3"); | 19 | UserGroupVerifier.CreateLocalGroup("testName3"); |
| 19 | var productA = this.CreatePackageInstaller("ProductA"); | 20 | var productA = this.CreatePackageInstaller("ProductA"); |
| @@ -39,7 +40,7 @@ namespace WixToolsetTest.MsiE2E | |||
| 39 | 40 | ||
| 40 | // Verify the rollback action reverts all Users changes. | 41 | // Verify the rollback action reverts all Users changes. |
| 41 | [RuntimeFact] | 42 | [RuntimeFact] |
| 42 | public void CanRollbackGroups() | 43 | public void CanRollbackNonDomainGroups() |
| 43 | { | 44 | { |
| 44 | UserGroupVerifier.CreateLocalGroup("testName3"); | 45 | UserGroupVerifier.CreateLocalGroup("testName3"); |
| 45 | var productFail = this.CreatePackageInstaller("ProductFail"); | 46 | var productFail = this.CreatePackageInstaller("ProductFail"); |
| @@ -65,7 +66,7 @@ namespace WixToolsetTest.MsiE2E | |||
| 65 | // Original code signalled repair mode by using "-f ", which silently | 66 | // Original code signalled repair mode by using "-f ", which silently |
| 66 | // terminated the command-line parsing, ignoring any parameters that followed. | 67 | // terminated the command-line parsing, ignoring any parameters that followed. |
| 67 | [RuntimeFact()] | 68 | [RuntimeFact()] |
| 68 | public void CanRepairGroupsWithCommandLineParameters() | 69 | public void CanRepairNonDomainGroupsWithCommandLineParameters() |
| 69 | { | 70 | { |
| 70 | var arguments = new string[] | 71 | var arguments = new string[] |
| 71 | { | 72 | { |
| @@ -82,6 +83,10 @@ namespace WixToolsetTest.MsiE2E | |||
| 82 | // Repair | 83 | // Repair |
| 83 | productWithCommandLineParameters.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments); | 84 | productWithCommandLineParameters.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments); |
| 84 | 85 | ||
| 86 | |||
| 87 | // Install | ||
| 88 | productWithCommandLineParameters.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments); | ||
| 89 | |||
| 85 | // Clean up | 90 | // Clean up |
| 86 | UserGroupVerifier.DeleteLocalGroup("testName1"); | 91 | UserGroupVerifier.DeleteLocalGroup("testName1"); |
| 87 | } | 92 | } |
| @@ -89,7 +94,7 @@ namespace WixToolsetTest.MsiE2E | |||
| 89 | 94 | ||
| 90 | // Verify that the groups specified in the authoring are created as expected on repair. | 95 | // Verify that the groups specified in the authoring are created as expected on repair. |
| 91 | [RuntimeFact()] | 96 | [RuntimeFact()] |
| 92 | public void CanRepairGroups() | 97 | public void CanRepairNonDomainGroups() |
| 93 | { | 98 | { |
| 94 | UserGroupVerifier.CreateLocalGroup("testName3"); | 99 | UserGroupVerifier.CreateLocalGroup("testName3"); |
| 95 | var productA = this.CreatePackageInstaller("ProductA"); | 100 | var productA = this.CreatePackageInstaller("ProductA"); |
| @@ -119,7 +124,7 @@ namespace WixToolsetTest.MsiE2E | |||
| 119 | 124 | ||
| 120 | // Verify that Installation fails if FailIfExists is set. | 125 | // Verify that Installation fails if FailIfExists is set. |
| 121 | [RuntimeFact] | 126 | [RuntimeFact] |
| 122 | public void FailsIfGroupExists() | 127 | public void FailsIfNonDomainGroupExists() |
| 123 | { | 128 | { |
| 124 | var productFailIfExists = this.CreatePackageInstaller("ProductFailIfExists"); | 129 | var productFailIfExists = this.CreatePackageInstaller("ProductFailIfExists"); |
| 125 | 130 | ||
| @@ -148,7 +153,7 @@ namespace WixToolsetTest.MsiE2E | |||
| 148 | { | 153 | { |
| 149 | var productRestrictedDomain = this.CreatePackageInstaller("ProductRestrictedDomain"); | 154 | var productRestrictedDomain = this.CreatePackageInstaller("ProductRestrictedDomain"); |
| 150 | 155 | ||
| 151 | string logFile = productRestrictedDomain.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, "TEMPDOMAIN=DOESNOTEXIST"); | 156 | string logFile = productRestrictedDomain.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, "TESTDOMAIN=DOESNOTEXIST"); |
| 152 | 157 | ||
| 153 | // Verify expected error message in the log file | 158 | // Verify expected error message in the log file |
| 154 | Assert.True(LogVerifier.MessageInLogFile(logFile, "CreateGroup: Error 0x8007054b: failed to find Domain DOESNOTEXIST.")); | 159 | Assert.True(LogVerifier.MessageInLogFile(logFile, "CreateGroup: Error 0x8007054b: failed to find Domain DOESNOTEXIST.")); |
| @@ -156,12 +161,13 @@ namespace WixToolsetTest.MsiE2E | |||
| 156 | 161 | ||
| 157 | // Verify that a group can be created with a group comment | 162 | // Verify that a group can be created with a group comment |
| 158 | [RuntimeFact] | 163 | [RuntimeFact] |
| 159 | public void CanCreateNewGroupWithComment() | 164 | public void CanCreateNewNonDomainGroupWithComment() |
| 160 | { | 165 | { |
| 161 | var productNewUserWithComment = this.CreatePackageInstaller("ProductNewGroupWithComment"); | 166 | var productNewUserWithComment = this.CreatePackageInstaller("ProductNewGroupWithComment"); |
| 162 | 167 | ||
| 163 | productNewUserWithComment.InstallProduct(); | 168 | productNewUserWithComment.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
| 164 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", "testComment1"); | 169 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", "testComment1"); |
| 170 | productNewUserWithComment.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | ||
| 165 | 171 | ||
| 166 | // clean up | 172 | // clean up |
| 167 | UserGroupVerifier.DeleteLocalGroup("testName1"); | 173 | UserGroupVerifier.DeleteLocalGroup("testName1"); |
| @@ -169,30 +175,33 @@ namespace WixToolsetTest.MsiE2E | |||
| 169 | 175 | ||
| 170 | // Verify that a comment can be added to an existing group | 176 | // Verify that a comment can be added to an existing group |
| 171 | [RuntimeFact] | 177 | [RuntimeFact] |
| 172 | public void CanAddCommentToExistingGroup() | 178 | public void CanAddCommentToExistingNonDomainGroup() |
| 173 | { | 179 | { |
| 174 | UserGroupVerifier.CreateLocalGroup("testName1"); | 180 | UserGroupVerifier.CreateLocalGroup("testName1"); |
| 175 | var productAddCommentToExistingUser = this.CreatePackageInstaller("ProductAddCommentToExistingGroup"); | 181 | var productAddCommentToExistingUser = this.CreatePackageInstaller("ProductAddCommentToExistingGroup"); |
| 176 | 182 | ||
| 177 | productAddCommentToExistingUser.InstallProduct(); | 183 | productAddCommentToExistingUser.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
| 178 | 184 | ||
| 179 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", "testComment1"); | 185 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", "testComment1"); |
| 180 | 186 | ||
| 187 | productAddCommentToExistingUser.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | ||
| 188 | |||
| 181 | // clean up | 189 | // clean up |
| 182 | UserGroupVerifier.DeleteLocalGroup("testName1"); | 190 | UserGroupVerifier.DeleteLocalGroup("testName1"); |
| 183 | } | 191 | } |
| 184 | 192 | ||
| 185 | // Verify that a comment can be repaired for a new group | 193 | // Verify that a comment can be repaired for a new group |
| 186 | [RuntimeFact] | 194 | [RuntimeFact] |
| 187 | public void CanRepairCommentOfNewGroup() | 195 | public void CanRepairCommentOfNewNonDomainGroup() |
| 188 | { | 196 | { |
| 189 | var productNewUserWithComment = this.CreatePackageInstaller("ProductNewGroupWithComment"); | 197 | var productNewUserWithComment = this.CreatePackageInstaller("ProductNewGroupWithComment"); |
| 190 | 198 | ||
| 191 | productNewUserWithComment.InstallProduct(); | 199 | productNewUserWithComment.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
| 192 | UserGroupVerifier.SetGroupComment(String.Empty, "testName1", ""); | 200 | UserGroupVerifier.SetGroupComment(String.Empty, "testName1", ""); |
| 193 | 201 | ||
| 194 | productNewUserWithComment.RepairProduct(); | 202 | productNewUserWithComment.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
| 195 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", "testComment1"); | 203 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", "testComment1"); |
| 204 | productNewUserWithComment.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | ||
| 196 | 205 | ||
| 197 | // clean up | 206 | // clean up |
| 198 | UserGroupVerifier.DeleteLocalGroup("testName1"); | 207 | UserGroupVerifier.DeleteLocalGroup("testName1"); |
| @@ -200,14 +209,15 @@ namespace WixToolsetTest.MsiE2E | |||
| 200 | 209 | ||
| 201 | // Verify that a comment can be changed for an existing group | 210 | // Verify that a comment can be changed for an existing group |
| 202 | [RuntimeFact] | 211 | [RuntimeFact] |
| 203 | public void CanChangeCommentOfExistingGroup() | 212 | public void CanChangeCommentOfExistingNonDomainGroup() |
| 204 | { | 213 | { |
| 205 | UserGroupVerifier.CreateLocalGroup("testName1"); | 214 | UserGroupVerifier.CreateLocalGroup("testName1"); |
| 206 | UserGroupVerifier.SetGroupComment(String.Empty, "testName1", "initialTestComment1"); | 215 | UserGroupVerifier.SetGroupComment(String.Empty, "testName1", "initialTestComment1"); |
| 207 | var productNewUserWithComment = this.CreatePackageInstaller("ProductNewGroupWithComment"); | 216 | var productNewUserWithComment = this.CreatePackageInstaller("ProductNewGroupWithComment"); |
| 208 | 217 | ||
| 209 | productNewUserWithComment.InstallProduct(); | 218 | productNewUserWithComment.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
| 210 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", "testComment1"); | 219 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", "testComment1"); |
| 220 | productNewUserWithComment.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | ||
| 211 | 221 | ||
| 212 | // clean up | 222 | // clean up |
| 213 | UserGroupVerifier.DeleteLocalGroup("testName1"); | 223 | UserGroupVerifier.DeleteLocalGroup("testName1"); |
| @@ -215,7 +225,7 @@ namespace WixToolsetTest.MsiE2E | |||
| 215 | 225 | ||
| 216 | // Verify that a comment can be rolled back for an existing group | 226 | // Verify that a comment can be rolled back for an existing group |
| 217 | [RuntimeFact] | 227 | [RuntimeFact] |
| 218 | public void CanRollbackCommentOfExistingGroup() | 228 | public void CanRollbackCommentOfExistingNonDomainGroup() |
| 219 | { | 229 | { |
| 220 | UserGroupVerifier.CreateLocalGroup("testName1"); | 230 | UserGroupVerifier.CreateLocalGroup("testName1"); |
| 221 | UserGroupVerifier.SetGroupComment(String.Empty, "testName1", "initialTestComment1"); | 231 | UserGroupVerifier.SetGroupComment(String.Empty, "testName1", "initialTestComment1"); |
| @@ -232,7 +242,7 @@ namespace WixToolsetTest.MsiE2E | |||
| 232 | 242 | ||
| 233 | // Verify that a comment can be deleted for an existing group | 243 | // Verify that a comment can be deleted for an existing group |
| 234 | [RuntimeFact] | 244 | [RuntimeFact] |
| 235 | public void CanDeleteCommentOfExistingGroup() | 245 | public void CanDeleteCommentOfExistingNonDomainGroup() |
| 236 | { | 246 | { |
| 237 | UserGroupVerifier.CreateLocalGroup("testName1"); | 247 | UserGroupVerifier.CreateLocalGroup("testName1"); |
| 238 | UserGroupVerifier.SetGroupComment(String.Empty, "testName1", "testComment1"); | 248 | UserGroupVerifier.SetGroupComment(String.Empty, "testName1", "testComment1"); |
| @@ -243,29 +253,64 @@ namespace WixToolsetTest.MsiE2E | |||
| 243 | // Verify that comment was removed. | 253 | // Verify that comment was removed. |
| 244 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", ""); | 254 | UserGroupVerifier.VerifyGroupComment(String.Empty, "testName1", ""); |
| 245 | 255 | ||
| 256 | |||
| 257 | productCommentDelete.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | ||
| 258 | |||
| 246 | // clean up | 259 | // clean up |
| 247 | UserGroupVerifier.DeleteLocalGroup("testName1"); | 260 | UserGroupVerifier.DeleteLocalGroup("testName1"); |
| 248 | } | 261 | } |
| 249 | 262 | ||
| 250 | // Verify that a comment can be deleted for an existing group | 263 | #endregion |
| 251 | [RuntimeFact] | 264 | |
| 252 | public void CanNestGroups() | 265 | #region Domain |
| 266 | // Verify that a domain group can be nested within a local group | ||
| 267 | [RuntimeFact(DomainRequired = true)] | ||
| 268 | public void CanNestDomainGroups() | ||
| 253 | { | 269 | { |
| 270 | var testDomain = System.Environment.UserDomainName; | ||
| 254 | var productNestedGroups = this.CreatePackageInstaller("ProductNestedGroups"); | 271 | var productNestedGroups = this.CreatePackageInstaller("ProductNestedGroups"); |
| 255 | 272 | ||
| 256 | productNestedGroups.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | 273 | productNestedGroups.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, $"TESTDOMAIN={testDomain}"); |
| 257 | 274 | ||
| 258 | // Verify group nested membership | 275 | // Verify group nested membership |
| 259 | UserGroupVerifier.VerifyIsMemberOf(String.Empty, "Authenticated Users", new string[] { "testName1", "testName2" }); | 276 | UserGroupVerifier.VerifyIsMemberOf(testDomain, "Domain Users", new string[] { "testName1", "testName2" }); |
| 260 | UserGroupVerifier.VerifyIsMemberOf(String.Empty, "Everyone", new string[] { "testName1" }); | 277 | //UserGroupVerifier.VerifyIsMemberOf(String.Empty, "Everyone", new string[] { "testName1" }); |
| 278 | |||
| 279 | UserGroupVerifier.VerifyIsNotMemberOf(testDomain, "Domain Users", new string[] { "testName3" }); | ||
| 280 | //UserGroupVerifier.VerifyIsNotMemberOf(String.Empty, "Everyone", new string[] { "testName2", "testName3" }); | ||
| 261 | 281 | ||
| 262 | UserGroupVerifier.VerifyIsNotMemberOf(String.Empty, "Authenticated Users", new string[] { "testName3" }); | 282 | productNestedGroups.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, $"TESTDOMAIN={testDomain}"); |
| 263 | UserGroupVerifier.VerifyIsNotMemberOf(String.Empty, "Everyone", new string[] { "testName2", "testName3" }); | ||
| 264 | 283 | ||
| 265 | // clean up | 284 | // clean up |
| 266 | UserGroupVerifier.DeleteLocalGroup("testName1"); | 285 | UserGroupVerifier.DeleteLocalGroup("testName1"); |
| 267 | UserGroupVerifier.DeleteLocalGroup("testName2"); | 286 | UserGroupVerifier.DeleteLocalGroup("testName2"); |
| 268 | UserGroupVerifier.DeleteLocalGroup("testName3"); | 287 | UserGroupVerifier.DeleteLocalGroup("testName3"); |
| 269 | } | 288 | } |
| 289 | |||
| 290 | // Verify the rollback action reverts all Users changes. | ||
| 291 | [RuntimeFact(DomainRequired = true)] | ||
| 292 | public void CanRollbackDomainGroups() | ||
| 293 | { | ||
| 294 | var testDomain = System.Environment.UserDomainName; | ||
| 295 | UserGroupVerifier.CreateLocalGroup("testName3"); | ||
| 296 | var productFail = this.CreatePackageInstaller("ProductFail"); | ||
| 297 | |||
| 298 | // make sure the user accounts are deleted before we start | ||
| 299 | UserGroupVerifier.DeleteLocalGroup("testName1"); | ||
| 300 | UserGroupVerifier.DeleteLocalGroup("testName2"); | ||
| 301 | |||
| 302 | productFail.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, $"TESTDOMAIN={testDomain}"); | ||
| 303 | |||
| 304 | // Verify added Users were removed on rollback. | ||
| 305 | Assert.False(UserGroupVerifier.GroupExists(String.Empty, "testName1"), String.Format("Group '{0}' was not removed on Rollback", "testName1")); | ||
| 306 | Assert.False(UserGroupVerifier.GroupExists(String.Empty, "testName2"), String.Format("Group '{0}' was not removed on Rollback", "testName2")); | ||
| 307 | |||
| 308 | // clean up | ||
| 309 | UserGroupVerifier.DeleteLocalGroup("testName1"); | ||
| 310 | UserGroupVerifier.DeleteLocalGroup("testName2"); | ||
| 311 | UserGroupVerifier.DeleteLocalGroup("testName3"); | ||
| 312 | } | ||
| 313 | |||
| 314 | #endregion | ||
| 270 | } | 315 | } |
| 271 | } | 316 | } |
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd b/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd index a2e67c89..ed1d50b6 100644 --- a/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd +++ b/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd | |||
| @@ -1,2 +1,3 @@ | |||
| 1 | SET RuntimeTestsEnabled=true | 1 | SET RuntimeTestsEnabled=true |
| 2 | SET RuntimeDomainTestsEnabled=true | ||
| 2 | dotnet test WixToolsetTest.MsiE2E.dll -v normal --logger trx | 3 | dotnet test WixToolsetTest.MsiE2E.dll -v normal --logger trx |
