summaryrefslogtreecommitdiff
path: root/src/ext/Util/ca/scaexec.cpp
diff options
context:
space:
mode:
authorBevan Weiss <bevan.weiss@gmail.com>2024-07-06 21:03:57 +1000
committerRob Mensching <rob@firegiant.com>2025-02-11 23:14:49 -0800
commit644276562dcadd65fcb0e9a7c06c704cdda36423 (patch)
treef42af115bf5354d1c1691c44d517388f6c369b16 /src/ext/Util/ca/scaexec.cpp
parent7b1bb025dea1d1e9e144cce0dcbba2d86f053b8f (diff)
downloadwix-644276562dcadd65fcb0e9a7c06c704cdda36423.tar.gz
wix-644276562dcadd65fcb0e9a7c06c704cdda36423.tar.bz2
wix-644276562dcadd65fcb0e9a7c06c704cdda36423.zip
Group Add/Remove working.
Local group membership Add/Remove working, however with BUILTIN local system groups .NET doesn't appear to locate them as either groups nor basic security Principals. Still needs work to fix the test for nested groups. Ideally with some way to test for domain groups. 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.cpp454
1 files changed, 254 insertions, 200 deletions
diff --git a/src/ext/Util/ca/scaexec.cpp b/src/ext/Util/ca/scaexec.cpp
index 5a750c6b..64f4c823 100644
--- a/src/ext/Util/ca/scaexec.cpp
+++ b/src/ext/Util/ca/scaexec.cpp
@@ -291,146 +291,6 @@ LExit:
291 return hr; 291 return hr;
292} 292}
293 293
294static HRESULT AddGroupToGroup(
295 __in LPWSTR wzMember,
296 __in LPCWSTR wzMemberDomain,
297 __in LPCWSTR wzGroup,
298 __in LPCWSTR wzGroupDomain
299)
300{
301 Assert(wzMember && *wzMember && wzMemberDomain && wzGroup && *wzGroup && wzGroupDomain);
302
303 HRESULT hr = S_OK;
304 IADsGroup* pGroup = NULL;
305 BSTR bstrMember = NULL;
306 BSTR bstrGroup = NULL;
307 LPWSTR pwzMember = NULL;
308 LPWSTR pwzServerName = NULL;
309 LOCALGROUP_MEMBERS_INFO_3 lgmi {};
310
311 GetDomainServerName(wzGroupDomain, &pwzServerName);
312
313 // Try adding it to the local group
314 if (wzMemberDomain)
315 {
316 hr = StrAllocFormatted(&pwzMember, L"%s\\%s", wzMemberDomain, wzMember);
317 ExitOnFailure(hr, "failed to allocate group domain string");
318 }
319
320 lgmi.lgrmi3_domainandname = (NULL == pwzMember ? wzMember : pwzMember);
321 NET_API_STATUS ui = ::NetLocalGroupAddMembers(pwzServerName, wzGroup, 3, reinterpret_cast<LPBYTE>(&lgmi), 1);
322 hr = HRESULT_FROM_WIN32(ui);
323 if (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr) // if they're already a member of the group don't report an error
324 {
325 hr = S_OK;
326 }
327
328 //
329 // If we failed, try active directory
330 //
331 if (FAILED(hr))
332 {
333 WcaLog(LOGMSG_VERBOSE, "Failed to add group: %ls, domain %ls to group: %ls, domain: %ls with error 0x%x. Attempting to use Active Directory", wzMember, wzMemberDomain, wzGroup, wzGroupDomain, hr);
334
335 hr = UserCreateADsPath(wzMemberDomain, wzMember, &bstrMember);
336 ExitOnFailure(hr, "failed to create group ADsPath for group: %ls domain: %ls", wzMember, wzMemberDomain);
337
338 hr = UserCreateADsPath(wzGroupDomain, wzGroup, &bstrGroup);
339 ExitOnFailure(hr, "failed to create group ADsPath for group: %ls domain: %ls", wzGroup, wzGroupDomain);
340
341 hr = ::ADsGetObject(bstrGroup, IID_IADsGroup, reinterpret_cast<void**>(&pGroup));
342 ExitOnFailure(hr, "Failed to get group '%ls'.", reinterpret_cast<WCHAR*>(bstrGroup));
343
344 hr = pGroup->Add(bstrMember);
345 if ((HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS) == hr) || (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr))
346 hr = S_OK;
347
348 ExitOnFailure(hr, "Failed to add group %ls to group '%ls'.", reinterpret_cast<WCHAR*>(bstrMember), reinterpret_cast<WCHAR*>(bstrGroup));
349 }
350
351LExit:
352 ReleaseStr(pwzServerName);
353 ReleaseStr(pwzMember);
354 ReleaseBSTR(bstrMember);
355 ReleaseBSTR(bstrGroup);
356 ReleaseObject(pGroup);
357
358 return hr;
359}
360
361static HRESULT RemoveGroupFromGroup(
362 __in LPWSTR wzMember,
363 __in LPCWSTR wzMemberDomain,
364 __in LPCWSTR wzGroup,
365 __in LPCWSTR wzGroupDomain
366)
367{
368 Assert(wzMember && *wzMember && wzMemberDomain && wzGroup && *wzGroup && wzGroupDomain);
369
370 HRESULT hr = S_OK;
371 IADsGroup* pGroup = NULL;
372 BSTR bstrMember = NULL;
373 BSTR bstrGroup = NULL;
374 LPWSTR pwzMember = NULL;
375 LPWSTR pwzServerName = NULL;
376 LOCALGROUP_MEMBERS_INFO_3 lgmi {};
377
378 GetDomainServerName(wzGroupDomain, &pwzServerName, DS_WRITABLE_REQUIRED);
379
380 // Try removing it from the local group
381 if (wzMemberDomain)
382 {
383 hr = StrAllocFormatted(&pwzMember, L"%s\\%s", wzMemberDomain, wzMember);
384 ExitOnFailure(hr, "failed to allocate group domain string");
385 }
386
387 lgmi.lgrmi3_domainandname = (NULL == pwzMember ? wzMember : pwzMember);
388 NET_API_STATUS ui = ::NetLocalGroupDelMembers(pwzServerName, wzGroup, 3, reinterpret_cast<LPBYTE>(&lgmi), 1);
389 hr = HRESULT_FROM_WIN32(ui);
390 if (HRESULT_FROM_WIN32(ERROR_MEMBER_NOT_IN_ALIAS) == hr
391 || HRESULT_FROM_WIN32(NERR_GroupNotFound) == hr
392 || HRESULT_FROM_WIN32(ERROR_NO_SUCH_MEMBER) == hr) // if they're already not a member of the group, or the group doesn't exist, don't report an error
393 {
394 hr = S_OK;
395 }
396
397 //
398 // If we failed, try active directory
399 //
400 if (FAILED(hr))
401 {
402 WcaLog(LOGMSG_VERBOSE, "Failed to remove group: %ls, domain %ls from group: %ls, domain: %ls with error 0x%x. Attempting to use Active Directory", wzMember, wzMemberDomain, wzGroup, wzGroupDomain, hr);
403
404 hr = UserCreateADsPath(wzMemberDomain, wzMember, &bstrMember);
405 ExitOnFailure(hr, "failed to create group ADsPath in order to remove group: %ls domain: %ls from a group", wzMember, wzMemberDomain);
406
407 hr = UserCreateADsPath(wzGroupDomain, wzGroup, &bstrGroup);
408 ExitOnFailure(hr, "failed to create group ADsPath in order to remove group from group: %ls domain: %ls", wzGroup, wzGroupDomain);
409
410 hr = ::ADsGetObject(bstrGroup, IID_IADsGroup, reinterpret_cast<void**>(&pGroup));
411 if ((HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)) // if parent group not found, no need to remove membership from group
412 {
413 hr = S_OK;
414 ExitFunction();
415 }
416 ExitOnFailure(hr, "Failed to get group '%ls'.", reinterpret_cast<WCHAR*>(bstrGroup));
417
418 hr = pGroup->Remove(bstrMember);
419 if ((HRESULT_FROM_WIN32(ERROR_MEMBER_NOT_IN_ALIAS) == hr)) // if already not a member, no need to worry about error
420 hr = S_OK;
421 ExitOnFailure(hr, "Failed to remove group %ls from group '%ls'.", reinterpret_cast<WCHAR*>(bstrMember), reinterpret_cast<WCHAR*>(bstrGroup));
422 }
423
424LExit:
425 ReleaseStr(pwzServerName);
426 ReleaseStr(pwzMember);
427 ReleaseBSTR(bstrMember);
428 ReleaseBSTR(bstrGroup);
429 ReleaseObject(pGroup);
430
431 return hr;
432}
433
434static HRESULT GetUserHasRight( 294static HRESULT GetUserHasRight(
435 __in LSA_HANDLE hPolicy, 295 __in LSA_HANDLE hPolicy,
436 __in PSID pUserSid, 296 __in PSID pUserSid,
@@ -842,7 +702,6 @@ LExit:
842} 702}
843 703
844static HRESULT RemoveGroupInternal( 704static HRESULT RemoveGroupInternal(
845 LPWSTR wzGroupCaData,
846 LPWSTR wzDomain, 705 LPWSTR wzDomain,
847 LPWSTR wzName, 706 LPWSTR wzName,
848 int iAttributes 707 int iAttributes
@@ -850,9 +709,6 @@ static HRESULT RemoveGroupInternal(
850{ 709{
851 HRESULT hr = S_OK; 710 HRESULT hr = S_OK;
852 711
853 LPWSTR pwz = NULL;
854 LPWSTR pwzGroup = NULL;
855 LPWSTR pwzGroupDomain = NULL;
856 LPWSTR pwzServerName = NULL; 712 LPWSTR pwzServerName = NULL;
857 713
858 // 714 //
@@ -871,41 +727,9 @@ static HRESULT RemoveGroupInternal(
871 } 727 }
872 ExitOnFailure(hr, "failed to delete group: %ls", wzName); 728 ExitOnFailure(hr, "failed to delete group: %ls", wzName);
873 } 729 }
874 else
875 {
876 //
877 // Remove the group from other groups
878 //
879 pwz = wzGroupCaData;
880 while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup)))
881 {
882 hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain);
883 730
884 if (FAILED(hr))
885 {
886 WcaLogError(hr, "failed to get domain for group: %ls, continuing anyway.", pwzGroup);
887 }
888 else
889 {
890 hr = RemoveGroupFromGroup(wzName, wzDomain, pwzGroup, pwzGroupDomain);
891 if (FAILED(hr))
892 {
893 WcaLogError(hr, "failed to remove group: %ls from group %ls, continuing anyway.", wzName, pwzGroup);
894 }
895 }
896 }
897
898 if (E_NOMOREITEMS == hr) // if there are no more items, all is well
899 {
900 hr = S_OK;
901 }
902
903 ExitOnFailure(hr, "failed to get next group from which to remove group:%ls", wzName);
904 }
905LExit: 731LExit:
906 ReleaseStr(pwzServerName); 732 ReleaseStr(pwzServerName);
907 ReleaseStr(pwzGroup);
908 ReleaseStr(pwzGroupDomain);
909 733
910 return hr; 734 return hr;
911} 735}
@@ -1392,6 +1216,7 @@ LExit:
1392 return WcaFinalize(er); 1216 return WcaFinalize(er);
1393} 1217}
1394 1218
1219
1395/******************************************************************** 1220/********************************************************************
1396 CreateGroup - CUSTOM ACTION ENTRY POINT for creating groups 1221 CreateGroup - CUSTOM ACTION ENTRY POINT for creating groups
1397 1222
@@ -1412,8 +1237,6 @@ extern "C" UINT __stdcall CreateGroup(
1412 LPWSTR pwzDomain = NULL; 1237 LPWSTR pwzDomain = NULL;
1413 LPWSTR pwzComment = NULL; 1238 LPWSTR pwzComment = NULL;
1414 LPWSTR pwzScriptKey = NULL; 1239 LPWSTR pwzScriptKey = NULL;
1415 LPWSTR pwzGroup = NULL;
1416 LPWSTR pwzGroupDomain = NULL;
1417 int iAttributes = 0; 1240 int iAttributes = 0;
1418 BOOL fInitializedCom = FALSE; 1241 BOOL fInitializedCom = FALSE;
1419 1242
@@ -1553,24 +1376,6 @@ extern "C" UINT __stdcall CreateGroup(
1553 } 1376 }
1554 } 1377 }
1555 MessageExitOnFailure(hr, msierrGRPFailedGroupCreate, "failed to create group: %ls", pwzName); 1378 MessageExitOnFailure(hr, msierrGRPFailedGroupCreate, "failed to create group: %ls", pwzName);
1556
1557 //
1558 // Add the groups to groups
1559 //
1560 while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup)))
1561 {
1562 hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain);
1563 ExitOnFailure(hr, "failed to get domain for group: %ls", pwzGroup);
1564
1565 WcaLog(LOGMSG_STANDARD, "Adding group %ls\\%ls to group %ls\\%ls", pwzDomain, pwzName, pwzGroupDomain, pwzGroup);
1566 hr = AddGroupToGroup(pwzName, pwzDomain, pwzGroup, pwzGroupDomain);
1567 MessageExitOnFailure(hr, msierrUSRFailedUserGroupAdd, "failed to add group: %ls to group %ls", pwzName, pwzGroup);
1568 }
1569 if (E_NOMOREITEMS == hr) // if there are no more items, all is well
1570 {
1571 hr = S_OK;
1572 }
1573 ExitOnFailure(hr, "failed to get next group in which to include group: %ls", pwzName);
1574 } 1379 }
1575 1380
1576LExit: 1381LExit:
@@ -1586,8 +1391,6 @@ LExit:
1586 ReleaseStr(pwzDomain); 1391 ReleaseStr(pwzDomain);
1587 ReleaseStr(pwzComment); 1392 ReleaseStr(pwzComment);
1588 ReleaseStr(pwzScriptKey); 1393 ReleaseStr(pwzScriptKey);
1589 ReleaseStr(pwzGroup);
1590 ReleaseStr(pwzGroupDomain);
1591 1394
1592 if (fInitializedCom) 1395 if (fInitializedCom)
1593 { 1396 {
@@ -1704,7 +1507,7 @@ extern "C" UINT __stdcall CreateGroupRollback(
1704 } 1507 }
1705 } 1508 }
1706 1509
1707 hr = RemoveGroupInternal(pwz, pwzDomain, pwzName, iAttributes); 1510 hr = RemoveGroupInternal(pwzDomain, pwzName, iAttributes);
1708 1511
1709LExit: 1512LExit:
1710 WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE); 1513 WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE);
@@ -1781,7 +1584,7 @@ extern "C" UINT __stdcall RemoveGroup(
1781 hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); 1584 hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
1782 ExitOnFailure(hr, "failed to read attributes from custom action data"); 1585 ExitOnFailure(hr, "failed to read attributes from custom action data");
1783 1586
1784 hr = RemoveGroupInternal(pwz, pwzDomain, pwzName, iAttributes); 1587 hr = RemoveGroupInternal(pwzDomain, pwzName, iAttributes);
1785 1588
1786LExit: 1589LExit:
1787 ReleaseStr(pwzData); 1590 ReleaseStr(pwzData);
@@ -1801,3 +1604,254 @@ LExit:
1801 1604
1802 return WcaFinalize(er); 1605 return WcaFinalize(er);
1803} 1606}
1607
1608HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
1609{
1610 HRESULT hr = S_OK;
1611 NET_API_STATUS er = ERROR_SUCCESS;
1612
1613 LPWSTR pwzData = NULL;
1614 LPWSTR pwz = NULL;
1615 LPWSTR pwzParentName = NULL;
1616 LPWSTR pwzParentDomain = NULL;
1617 LPWSTR pwzChildName = NULL;
1618 LPWSTR pwzChildDomain = NULL;
1619 int iAttributes = 0;
1620 LPWSTR pwzChildFullName = NULL;
1621 LPWSTR pwzServerName = NULL;
1622 LOCALGROUP_MEMBERS_INFO_3 memberInfo3 = {};
1623 WCA_CASCRIPT_HANDLE phRollbackScript = NULL;
1624
1625 if (isRollback)
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");
1637
1638 WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData);
1639
1640 //
1641 // Read in the CustomActionData
1642 //
1643 pwz = pwzData;
1644 hr = WcaReadStringFromCaData(&pwz, &pwzParentName);
1645 ExitOnFailure(hr, "failed to read group name from custom action data");
1646
1647 hr = WcaReadStringFromCaData(&pwz, &pwzParentDomain);
1648 ExitOnFailure(hr, "failed to read domain from custom action data");
1649
1650 hr = WcaReadStringFromCaData(&pwz, &pwzChildName);
1651 ExitOnFailure(hr, "failed to read group comment from custom action data");
1652
1653 hr = WcaReadStringFromCaData(&pwz, &pwzChildDomain);
1654 ExitOnFailure(hr, "failed to read group comment from custom action data");
1655
1656 hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
1657 ExitOnFailure(hr, "failed to read attributes from custom action data");
1658
1659 hr = GetDomainServerName(pwzParentDomain, &pwzServerName, DS_WRITABLE_REQUIRED);
1660 ExitOnFailure(hr, "failed to contact domain server %ls", pwzParentDomain);
1661
1662 if (*pwzChildDomain)
1663 {
1664 StrAllocFormatted(&pwzChildFullName, L"%ls\\%ls", pwzChildDomain, pwzChildName);
1665 }
1666 else
1667 {
1668 StrAllocFormatted(&pwzChildFullName, L"%ls", pwzChildName);
1669 }
1670 memberInfo3.lgrmi3_domainandname = pwzChildFullName;
1671
1672 if (remove)
1673 {
1674 er = ::NetLocalGroupDelMembers(pwzServerName, pwzParentName, 3, (LPBYTE)&memberInfo3, 1);
1675 }
1676 else
1677 {
1678 er = ::NetLocalGroupAddMembers(pwzServerName, pwzParentName, 3, (LPBYTE)&memberInfo3, 1);
1679 }
1680 hr = HRESULT_FROM_WIN32(er);
1681
1682 if (S_OK == hr && !isRollback)
1683 {
1684 // we need to log rollback data, we can just use exactly the same data we used to do the initial action though
1685 WcaCaScriptWriteString(phRollbackScript, pwzParentName);
1686 WcaCaScriptWriteString(phRollbackScript, pwzParentDomain);
1687 WcaCaScriptWriteString(phRollbackScript, pwzChildName);
1688 WcaCaScriptWriteString(phRollbackScript, pwzChildDomain);
1689 WcaCaScriptWriteNumber(phRollbackScript, iAttributes);
1690 WcaCaScriptFlush(phRollbackScript);
1691 WcaCaScriptClose(phRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE);
1692 }
1693
1694 if (remove)
1695 {
1696 if (HRESULT_FROM_WIN32(NERR_GroupNotFound) == hr
1697 || HRESULT_FROM_WIN32(ERROR_NO_SUCH_MEMBER) == hr
1698 || HRESULT_FROM_WIN32(ERROR_MEMBER_NOT_IN_ALIAS) == hr)
1699 {
1700 hr = S_OK;
1701 }
1702 }
1703 else
1704 {
1705 if (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr)
1706 {
1707 hr = S_OK;
1708 }
1709 }
1710
1711LExit:
1712 ReleaseStr(pwzData);
1713 ReleaseStr(pwzParentName);
1714 ReleaseStr(pwzParentDomain);
1715 ReleaseStr(pwzChildName);
1716 ReleaseStr(pwzChildDomain);
1717 ReleaseStr(pwzChildFullName);
1718 ReleaseStr(pwzServerName);
1719
1720 if (SCAG_NON_VITAL & iAttributes)
1721 {
1722 return S_OK;
1723 }
1724 return hr;
1725}
1726
1727/********************************************************************
1728 AddGroupmembership - CUSTOM ACTION ENTRY POINT for creating groups
1729
1730 Input: deferred CustomActionData -
1731 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes
1732 * *****************************************************************/
1733extern "C" UINT __stdcall AddGroupMembership(
1734 __in MSIHANDLE hInstall
1735)
1736{
1737 //AssertSz(0, "Debug AddGroupMembership");
1738
1739 HRESULT hr = S_OK;
1740
1741 BOOL fInitializedCom = FALSE;
1742
1743 hr = WcaInitialize(hInstall, "AddGroupMembership");
1744 ExitOnFailure(hr, "failed to initialize");
1745
1746 hr = ::CoInitialize(NULL);
1747 ExitOnFailure(hr, "failed to initialize COM");
1748 fInitializedCom = TRUE;
1749
1750 hr = AlterGroupMembership(false, false);
1751
1752LExit:
1753 if (fInitializedCom)
1754 {
1755 ::CoUninitialize();
1756 }
1757 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILED : ERROR_SUCCESS);
1758}
1759
1760/********************************************************************
1761 AddGroupmembership - CUSTOM ACTION ENTRY POINT for creating groups
1762
1763 Input: deferred CustomActionData -
1764 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes
1765 * *****************************************************************/
1766extern "C" UINT __stdcall AddGroupMembershipRollback(
1767 __in MSIHANDLE hInstall
1768)
1769{
1770 //AssertSz(0, "Debug AddGroupMembershipRollback");
1771
1772 HRESULT hr = S_OK;
1773
1774 BOOL fInitializedCom = FALSE;
1775
1776 hr = WcaInitialize(hInstall, "AddGroupMembershipRollback");
1777 ExitOnFailure(hr, "failed to initialize");
1778
1779 hr = ::CoInitialize(NULL);
1780 ExitOnFailure(hr, "failed to initialize COM");
1781 fInitializedCom = TRUE;
1782
1783 hr = AlterGroupMembership(true, true);
1784
1785LExit:
1786 if (fInitializedCom)
1787 {
1788 ::CoUninitialize();
1789 }
1790 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILED : ERROR_SUCCESS);
1791}
1792
1793/********************************************************************
1794 RemoveGroupMembership - CUSTOM ACTION ENTRY POINT for creating groups
1795
1796 Input: deferred CustomActionData -
1797 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes
1798 * *****************************************************************/
1799extern "C" UINT __stdcall RemoveGroupMembership(
1800 __in MSIHANDLE hInstall
1801)
1802{
1803 //AssertSz(0, "Debug RemoveGroupMembership");
1804
1805 HRESULT hr = S_OK;
1806
1807 BOOL fInitializedCom = FALSE;
1808
1809 hr = WcaInitialize(hInstall, "RemoveGroupMembership");
1810 ExitOnFailure(hr, "failed to initialize");
1811
1812 hr = ::CoInitialize(NULL);
1813 ExitOnFailure(hr, "failed to initialize COM");
1814 fInitializedCom = TRUE;
1815
1816 hr = AlterGroupMembership(true, false);
1817
1818LExit:
1819 if (fInitializedCom)
1820 {
1821 ::CoUninitialize();
1822 }
1823 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILED : ERROR_SUCCESS);
1824}
1825
1826/********************************************************************
1827 RemoveGroupMembershipRollback - CUSTOM ACTION ENTRY POINT for creating groups
1828
1829 Input: deferred CustomActionData -
1830 ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes
1831 * *****************************************************************/
1832extern "C" UINT __stdcall RemoveGroupMembershipRollback(
1833 __in MSIHANDLE hInstall
1834)
1835{
1836 //AssertSz(0, "Debug RemoveGroupMembershipRollback");
1837
1838 HRESULT hr = S_OK;
1839
1840 BOOL fInitializedCom = FALSE;
1841
1842 hr = WcaInitialize(hInstall, "RemoveGroupMembershipRollback");
1843 ExitOnFailure(hr, "failed to initialize");
1844
1845 hr = ::CoInitialize(NULL);
1846 ExitOnFailure(hr, "failed to initialize COM");
1847 fInitializedCom = TRUE;
1848
1849 hr = AlterGroupMembership(false, true);
1850
1851LExit:
1852 if (fInitializedCom)
1853 {
1854 ::CoUninitialize();
1855 }
1856 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILED : ERROR_SUCCESS);
1857}