aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Util/ca/scaexec.cpp
diff options
context:
space:
mode:
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}