@@ -716,7 +716,7 @@ static HRESULT RemoveGroupInternal(
716716 //
717717 if (!(SCAG_DONT_CREATE_GROUP & iAttributes))
718718 {
719- GetDomainServerName (wzDomain, &pwzServerName, DS_WRITABLE_REQUIRED);
719+ hr = GetDomainFromServerName ( &pwzServerName, wzDomain , DS_WRITABLE_REQUIRED);
720720
721721 NET_API_STATUS er = ::NetLocalGroupDel (pwzServerName, wzName);
722722 hr = HRESULT_FROM_WIN32 (er);
@@ -1218,9 +1218,13 @@ extern "C" UINT __stdcall RemoveUser(
12181218
12191219
12201220/* *******************************************************************
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)
12221224
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
12241228 * *****************************************************************/
12251229extern " C" UINT __stdcall CreateGroup (
12261230 __in MSIHANDLE hInstall
@@ -1281,8 +1285,8 @@ extern "C" UINT __stdcall CreateGroup(
12811285
12821286 if (!(SCAG_DONT_CREATE_GROUP & iAttributes))
12831287 {
1284- hr = GetDomainServerName (pwzDomain, &pwzServerName, DS_WRITABLE_REQUIRED);
1285- ExitOnFailure (hr, " failed to find Domain %ls." , pwzDomain);
1288+ hr = GetDomainFromServerName ( &pwzServerName, pwzDomain , DS_WRITABLE_REQUIRED);
1289+ ExitOnFailure (hr, " failed to find writable server for domain %ls." , pwzDomain);
12861290
12871291 // Set the group's comment
12881292 if (SCAG_REMOVE_COMMENT & iAttributes)
@@ -1304,7 +1308,7 @@ extern "C" UINT __stdcall CreateGroup(
13041308 {
13051309 if (SCAG_FAIL_IF_EXISTS & iAttributes)
13061310 {
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);
13081312 }
13091313
13101314 hr = S_OK; // Make sure that we don't report this situation as an error
@@ -1359,7 +1363,7 @@ extern "C" UINT __stdcall CreateGroup(
13591363 hr = SetGroupComment (pwzServerName, pwzName, L" " );
13601364 if (FAILED (hr))
13611365 {
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);
13631367 hr = S_OK;
13641368 }
13651369 }
@@ -1368,14 +1372,14 @@ extern "C" UINT __stdcall CreateGroup(
13681372 hr = SetGroupComment (pwzServerName, pwzName, pwzComment);
13691373 if (FAILED (hr))
13701374 {
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);
13721376 hr = S_OK;
13731377 }
13741378 }
13751379 }
13761380 }
13771381 }
1378- MessageExitOnFailure (hr, msierrGRPFailedGroupCreate, " failed to create group: %ls" , pwzName);
1382+ MessageExitOnFailure (hr, msierrGRPFailedGroupCreate, " failed to create group: %ls\\ %ls " , pwzDomain , pwzName);
13791383 }
13801384
13811385LExit:
@@ -1391,6 +1395,7 @@ extern "C" UINT __stdcall CreateGroup(
13911395 ReleaseStr (pwzDomain);
13921396 ReleaseStr (pwzComment);
13931397 ReleaseStr (pwzScriptKey);
1398+ ReleaseStr (pwzServerName);
13941399
13951400 if (fInitializedCom )
13961401 {
@@ -1412,6 +1417,11 @@ extern "C" UINT __stdcall CreateGroup(
14121417
14131418/* *******************************************************************
14141419 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
14151425
14161426 * *****************************************************************/
14171427extern " C" UINT __stdcall CreateGroupRollback (
@@ -1429,7 +1439,7 @@ extern "C" UINT __stdcall CreateGroupRollback(
14291439 LPWSTR pwzName = NULL ;
14301440 LPWSTR pwzDomain = NULL ;
14311441 LPWSTR pwzComment = NULL ;
1432- int iAttributes = 0 ;
1442+ int iRollbackAttributes = 0 ;
14331443 BOOL fInitializedCom = FALSE ;
14341444
14351445 WCA_CASCRIPT_HANDLE hRollbackScript = NULL ;
@@ -1454,7 +1464,7 @@ extern "C" UINT __stdcall CreateGroupRollback(
14541464 //
14551465 pwz = pwzData;
14561466 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" );
14581468
14591469 hr = WcaReadStringFromCaData (&pwz, &pwzName);
14601470 ExitOnFailure (hr, " failed to read name from custom action data" );
@@ -1465,8 +1475,8 @@ extern "C" UINT __stdcall CreateGroupRollback(
14651475 hr = WcaReadStringFromCaData (&pwz, &pwzComment);
14661476 ExitOnFailure (hr, " failed to read comment from custom action data" );
14671477
1468- hr = WcaReadIntegerFromCaData (&pwz, &iAttributes );
1469- ExitOnFailure (hr, " failed to read attributes from custom action data" );
1478+ hr = WcaReadIntegerFromCaData (&pwz, &iRollbackAttributes );
1479+ ExitOnFailure (hr, " failed to read rollback attributes from custom action data" );
14701480
14711481 // Best effort to read original configuration from CreateUser.
14721482 hr = WcaCaScriptOpen (WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE , pwzScriptKey, &hRollbackScript);
@@ -1502,12 +1512,12 @@ extern "C" UINT __stdcall CreateGroupRollback(
15021512 }
15031513 else
15041514 {
1505- iAttributes |= iOriginalAttributes;
1515+ iRollbackAttributes |= iOriginalAttributes;
15061516 }
15071517 }
15081518 }
15091519
1510- hr = RemoveGroupInternal (pwzDomain, pwzName, iAttributes );
1520+ hr = RemoveGroupInternal (pwzDomain, pwzName, iRollbackAttributes );
15111521
15121522LExit:
15131523 WcaCaScriptClose (hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE);
@@ -1535,9 +1545,12 @@ extern "C" UINT __stdcall CreateGroupRollback(
15351545
15361546
15371547/* *******************************************************************
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
15391552
1540- Input: deferred CustomActionData - Name\tDomain
1553+ Input: commit CustomActionData - Name\tDomain\tComment\tAttributes
15411554 * *****************************************************************/
15421555extern " C" UINT __stdcall RemoveGroup (
15431556 MSIHANDLE hInstall
@@ -1605,7 +1618,7 @@ extern "C" UINT __stdcall RemoveGroup(
16051618 return WcaFinalize (er);
16061619}
16071620
1608- HRESULT AlterGroupMembership (bool remove, bool isRollback = false )
1621+ HRESULT AlterGroupMembership (bool remove, bool isRollback)
16091622{
16101623 HRESULT hr = S_OK;
16111624 NET_API_STATUS er = ERROR_SUCCESS;
@@ -1617,22 +1630,13 @@ HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
16171630 LPWSTR pwzChildName = NULL ;
16181631 LPWSTR pwzChildDomain = NULL ;
16191632 int iAttributes = 0 ;
1633+ LPWSTR pwzScriptKey = NULL ;
16201634 LPWSTR pwzChildFullName = NULL ;
16211635 LPWSTR pwzServerName = NULL ;
16221636 LOCALGROUP_MEMBERS_INFO_3 memberInfo3 = {};
1623- WCA_CASCRIPT_HANDLE phRollbackScript = NULL ;
1637+ WCA_CASCRIPT_HANDLE hRollbackScript = NULL ;
16241638
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- }
1639+ hr = WcaGetProperty (L" CustomActionData" , &pwzData);
16361640 ExitOnFailure (hr, " failed to get CustomActionData" );
16371641
16381642 WcaLog (LOGMSG_TRACEONLY, " CustomActionData: %ls" , pwzData);
@@ -1656,8 +1660,28 @@ HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
16561660 hr = WcaReadIntegerFromCaData (&pwz, &iAttributes);
16571661 ExitOnFailure (hr, " failed to read attributes from custom action data" );
16581662
1659- hr = GetDomainServerName (pwzParentDomain, &pwzServerName, DS_WRITABLE_REQUIRED);
1660- ExitOnFailure (hr, " failed to contact domain server %ls" , pwzParentDomain);
1663+ hr = WcaReadStringFromCaData (&pwz, &pwzScriptKey);
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);
16611685
16621686 if (*pwzChildDomain)
16631687 {
@@ -1679,16 +1703,13 @@ HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
16791703 }
16801704 hr = HRESULT_FROM_WIN32 (er);
16811705
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
16821708 if (S_OK == hr && !isRollback)
16831709 {
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);
1710+ // we create a script file, the rollback matching this scriptkey will occur if the file exists
1711+ hr = WcaCaScriptCreate (WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE , pwzScriptKey, FALSE , &hRollbackScript);
1712+ WcaCaScriptClose (hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE);
16921713 }
16931714
16941715 if (remove)
@@ -1716,6 +1737,7 @@ HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
17161737 ReleaseStr (pwzChildDomain);
17171738 ReleaseStr (pwzChildFullName);
17181739 ReleaseStr (pwzServerName);
1740+ ReleaseStr (pwzScriptKey);
17191741
17201742 if (SCAG_NON_VITAL & iAttributes)
17211743 {
@@ -1725,10 +1747,12 @@ HRESULT AlterGroupMembership(bool remove, bool isRollback = false)
17251747}
17261748
17271749/* *******************************************************************
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)
17291753
17301754 Input: deferred CustomActionData -
1731- ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes
1755+ ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey
17321756 * *****************************************************************/
17331757extern " C" UINT __stdcall AddGroupMembership (
17341758 __in MSIHANDLE hInstall
@@ -1758,10 +1782,13 @@ extern "C" UINT __stdcall AddGroupMembership(
17581782}
17591783
17601784/* *******************************************************************
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)
17621789
17631790 Input: deferred CustomActionData -
1764- ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes
1791+ ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey
17651792 * *****************************************************************/
17661793extern " C" UINT __stdcall AddGroupMembershipRollback (
17671794 __in MSIHANDLE hInstall
@@ -1791,10 +1818,12 @@ extern "C" UINT __stdcall AddGroupMembershipRollback(
17911818}
17921819
17931820/* *******************************************************************
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)
17951824
17961825 Input: deferred CustomActionData -
1797- ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes
1826+ ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey
17981827 * *****************************************************************/
17991828extern " C" UINT __stdcall RemoveGroupMembership (
18001829 __in MSIHANDLE hInstall
@@ -1824,10 +1853,13 @@ extern "C" UINT __stdcall RemoveGroupMembership(
18241853}
18251854
18261855/* *******************************************************************
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)
18281860
18291861 Input: deferred CustomActionData -
1830- ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes
1862+ ParentGroupName\tParentGroupDomain\tChildGroupName\tChildGroupDomain\tAttributes\tScriptkey
18311863 * *****************************************************************/
18321864extern " C" UINT __stdcall RemoveGroupMembershipRollback (
18331865 __in MSIHANDLE hInstall
0 commit comments